解析(读取)漂亮的文本表
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 语言):
module petl
- 不起作用,无法读取 +--------+--------+-------------------+
np.fromtxt
或 smth 也不起作用,因为没有数组
module asciitable
不行,
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: ['+----------+------------------------------------------------------------+---------------+-----------------+----------------+--------------------+-----------------------+']
当然我尝试了所有的参数组合
- 是的,尝试了简单(但不是)的方法并使用了正则表达式。但如果“行”超过 1 行,则很难捕获所有异常。
- 也尝试过简单的
split
,但它也很不愉快...
我听说过用 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']]}
我找不到任何关于读取 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 语言):
module petl
- 不起作用,无法读取+--------+--------+-------------------+
np.fromtxt
或 smth 也不起作用,因为没有数组module asciitable
不行,
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: ['+----------+------------------------------------------------------------+---------------+-----------------+----------------+--------------------+-----------------------+']
当然我尝试了所有的参数组合
- 是的,尝试了简单(但不是)的方法并使用了正则表达式。但如果“行”超过 1 行,则很难捕获所有异常。
- 也尝试过简单的
split
,但它也很不愉快...
我听说过用 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']]}