解析(读取)漂亮的文本表

Parsing (reading) prettytable text tables

我找不到任何关于读取 ascii tables (prettytable-looking) 的信息。 我需要解析一些像这样的 tables:

+--------+--------+-------------------+
|               Planets               |
+--------+--------+-------------------+
| Planet | R (km) | mass (x 10^29 kg) |
+--------+--------+-------------------+
|  Sun   | 696000 |    1989100000     |
|(Solar) |        |                   |
+--------+--------+-------------------+
| Earth  |  6371  |      5973.6       |
+--------+--------+-------------------+
|  Moon  |  1737  |       73.5        |
+--------+--------+-------------------+
|  Mars  |  3390  |      641.85       |
+--------+--------+-------------------+

如您所见,这个table包含标题和副标题,但这不是主要问题。 这是我尝试解析它的方式(所有尝试都在 Python 中,可能存在更多 suitable 语言):

asciitable.read("sample.txt",delimiter='|',guess=False,numpy=False, quotechar="'")
InconsistentTableError: Number of header columns (1) inconsistent with data columns (9) at data line 0
Header values: ['+----------+------------------------------------------------------------+---------------+-----------------+----------------+--------------------+-----------------------+']

当然我尝试了所有的参数组合

我听说过用 0 和 1 代替 numpy,但是我的 table 太难了。请帮忙。

我认为你可以使用 python 来做到这一点,通过几次你可以将其转换成适合你需要的东西。

table_str = """
+--------+--------+-------------------+
|               Planets               |
+--------+--------+-------------------+
| Planet | R (km) | mass (x 10^29 kg) |
+--------+--------+-------------------+
|  Sun   | 696000 |    1989100000     |
|(Solar) |        |                   |
+--------+--------+-------------------+
| Earth  |  6371  |      5973.6       |
+--------+--------+-------------------+
|  Moon  |  1737  |       73.5        |
+--------+--------+-------------------+
|  Mars  |  3390  |      641.85       |
+--------+--------+-------------------+
"""

table_list = [
    [item.strip() for item in line.split('|') if item]  # maintain the number of columns in rows.
    for line in table_str.strip().split('\n')
    if '+-' not in line  # discard +-
]

column_count = len(table_list[1])
row_idx_to_remove = list()
for row_idx, row in enumerate(table_list[2:], start=2):
    if any(not c for c in row):  # A multiline column entry
        row_idx_to_remove.append(row_idx)
        for col_idx, col in enumerate(table_list[row_idx - 1]):
            table_list[row_idx - 1][col_idx] += row[col_idx]

# Remove the rows that have already been merged into previous ones.
for idx in row_idx_to_remove:
    del table_list[idx]

table_dict = {'Name': table_list[0][0], 'Column Names': table_list[1], 'Rows': table_list[2:]}

print(table_dict)
print(table_list)

输出:

{'Name': 'Planets', 'Column Names': ['Planet', 'R (km)', 'mass (x 10^29 kg)'], 'Rows': [['Sun(Solar)', '696000', '1989100000'], ['Earth', '6371', '5973.6'], ['Moon', '1737', '73.5'], ['Mars', '3390', '641.85']]}
[['Planets'], ['Planet', 'R (km)', 'mass (x 10^29 kg)'], ['Sun(Solar)', '696000', '1989100000'], ['Earth', '6371', '5973.6'], ['Moon', '1737', '73.5'], ['Mars', '3390', '641.85']]

此实现不处理行中的空列,也不处理一行中每一列都不止一行的情况。

您也可以使用 re.split,并在包含 +- 的行上拆分,然后您可以处理任何包含此实现的边缘情况的行。

编辑: 这是一个使用 re.split:

的实现
import re


def parse_ascii_table(ascii_table):
    table_re_list = re.split(r'\+[+-]+', ascii_table)
    table_list = [l.strip().replace('\n', '') for l in table_re_list if l.strip()]
    table = {'Title': table_list[0].replace('|', '').strip(),
             'Column Names': [ch.strip() for ch in table_list[1].split('|') if ch.strip()],
             'Rows': list()}
    for row in table_list[2:]:
        joined_row = ['' for _ in range(len(row))]
        for lines in [line for line in row.split('||')]:
            line_part = [i.strip() for i in lines.split('|') if i]
            joined_row = [i + j for i, j in zip(joined_row, line_part)]
        table['Rows'].append(joined_row)
    return table


table_str = """
+--------+--------+-------------------+
|               Planets               |
+--------+--------+-------------------+
| Planet | R (km) | mass (x 10^29 kg) |
+--------+--------+-------------------+
|  Sun   | 696000 |    1989100000     |
|(Solar) |        |                   |
+--------+--------+-------------------+
| Earth  |  6371  |      5973.6       |
+--------+--------+-------------------+
|  Moon  |  1737  |       73.5        |
+--------+--------+-------------------+
|  Mars  |  3390  |      641.85       |
+--------+--------+-------------------+
"""
print(parse_ascii_table(table_str))

输出:

{'Title': 'Planets', 'Column Names': ['Planet', 'R (km)', 'mass (x 10^29 kg)'], 'Rows': [['Sun(Solar)', '696000', '1989100000'], ['Earth', '6371', '5973.6'], ['Moon', '1737', '73.5'], ['Mars', '3390', '641.85']]}