
本文详解如何将格式化的 sql 查询输出字符串(含表头与多行数据)解析为结构化字典列表,支持 python 2/3,兼顾空格分隔、空白行和字段对齐等常见边界情况。
本文详解如何将格式化的 sql 查询输出字符串(含表头与多行数据)解析为结构化字典列表,支持 python 2/3,兼顾空格分隔、空白行和字段对齐等常见边界情况。
在处理命令行 SQL 工具(如 psql -t 或 sqlite3 -line)的原始输出时,我们常遇到类似表格的字符串:首行为列名,次行为分隔线(如 =============, -, ---),随后是多行数据。这类文本虽非标准 CSV,但可通过轻量解析转化为可直接用于后续逻辑的 Python 对象数组(即 List[Dict[str, str]])。本文提供健壮、跨版本兼容的实现方案。
核心思路:分离头尾 → 提取字段 → 行映射为字典
关键步骤包括:
- 安全跳过分隔线(不依赖固定行号);
- 按空白符拆分列名与每行值(适配多空格对齐);
- 使用 zip(header, values) 实现字段名与值的动态绑定;
- 过滤空行或仅含空白字符的行。
以下为推荐实现(Python 3 风格,简洁清晰):
def parse_sql_table_string(text: str) -> list:
lines = [line.strip() for line in text.splitlines() if line.strip()]
# 安全提取表头:跳过首行分隔线(支持任意长度的'='、'-'等)
if not lines:
return []
header = lines[0].split()
# 找到第一个非分隔线的行作为数据起始(更鲁棒于格式变化)
data_start = 1
while data_start < len(lines) and (
set(lines[data_start]) <= {'=', '-', ' '} or
not lines[data_start]
):
data_start += 1
rows = lines[data_start:]
result = []
for row in rows:
if not row: # 跳过空行
continue
values = row.split() # 自动压缩连续空格
if len(values) >= len(header):
# 截断超长行,避免 KeyError;也可选择 warn 或 raise
mapped = dict(zip(header, values[:len(header)]))
result.append(mapped)
return result
# 示例使用
text = '''enable id
=============
f avc-qwqwq
t abd-rrtrtr
f rec-yyuyu
'''
print(parse_sql_table_string(text))
# 输出:
# [{'enable': 'f', 'id': 'avc-qwqwq'},
# {'enable': 't', 'id': 'abd-rrtrtr'},
# {'enable': 'f', 'id': 'rec-yyuyu'}]Python 2 兼容性适配要点
Python 2 不支持 *args 解包语法(如 header_str, _, *rows_str = ...),且 print 是语句而非函数。因此需改用迭代器显式消费:
def parse_sql_table_string_py2(text):
lines = [line.strip() for line in text.splitlines() if line.strip()]
if not lines:
return []
header = lines[0].split()
data_start = 1
while data_start < len(lines) and (
set(lines[data_start]) <= set('= -') or not lines[data_start]
):
data_start += 1
rows = lines[data_start:]
result = []
for row in rows:
if not row:
continue
values = row.split()
if len(values) >= len(header):
result.append(dict(zip(header, values[:len(header)])))
return result✅ 注意事项
- 字段对齐问题:若列值含空格(如 org name),split() 会错误切分。此时应改用正则 re.split(r'\s{2,}', row) 或按列宽硬解析(需先分析表头位置);
- 类型转换:当前返回全为字符串。如需布尔('f'→False, 't'→True)或数字,可在 dict() 构造后添加映射逻辑;
- 缺失值处理:zip 会截断较长行,但忽略短行可能导致键缺失。建议增加校验:if len(values) != len(header): raise ValueError(...);
- 编码安全:Python 2 中注意输入是否为 unicode,必要时加 .decode('utf-8')。
通过以上方法,你可将任意结构化 SQL 文本输出可靠地转化为内存中可用的对象数组,无缝接入 Pandas、JSON 序列化或 Web API 响应等下游流程。










