反序列化序列化表或矩形化文本行列表

时间:2017-03-25 12:07:00

标签: csv pdf text command-line transformation

有时我的文本表不在列旁边的普通表单列中,而是列在列之后的列,即表的所有列在各个文本行上相互列出。 (例如,当您从PDF表格中复制粘贴表格时会发生这种情况。)

这是一个例子。正确的表格如下:

Date        |  From - To              |  Flight   |  Departs Arrives        
------------|-------------------------|-----------|-------------------------
29-Jun-17   |  Sydney - Beijing       |  EK174    |  19:40 05:30 (30-Jun-17)
05-Jul-17   |  Beijing - Frankfurt    |  EK931    |  14:00 18:15            
12-Aug-17   |  Frankfurt - Shanghai   |  EK736    |  20:00 13:05 (13-Aug-17)
13-Aug-17   |  Shanghai - Sydney      |  EK175    |  19:35 08:10 (14-Aug-17)

但是我的数据如下:

Date
29-Jun-17 
05-Jul-17 
12-Aug-17 
13-Aug-17
From - To
Sydney - Beijing 
Beijing - Frankfurt 
Frankfurt - Shanghai 
Shanghai - Sydney
Flight 
EK174 
EK931 
EK736 
EK175
Departs Arrives
19:40 05:30 (30-Jun-17)
14:00 18:15 
20:00 13:05 (13-Aug-17)
19:35 08:10 (14-Aug-17)

我的问题: 是否有一个命令行工具将此列列表转换为前面提到的表格,它显然类似于什么? (基于unix的工具)显然需要一些帮助来将列表切割成列,例如,参数每列有多少行或类似的东西。

此外,这在我看来是转换问题。这是否在某些指定术语下已知(以便更容易找到具有该术语的Internet搜索的工具)? - 我称之为 ad hoc 类似" 矩阵化列表"或" 反序列化序列化表格" ...

2 个答案:

答案 0 :(得分:1)

我建议awkgawk)+ pr方法:
首先,我们将输入文件拆分为5个单独的文件(每个文件用于单独的模式):

awk '/Date|From - To|Flight|Departs Arrives/{gsub(/^ +| +$/, "", $0);fn=gensub(/[ -]+/, "-","g",$0); 
print $0 > "/tmp/"fn; next}{print > "/tmp/"fn;}' testfile

上述命令会在每个指定模式testfile

的每次出现时将输入文件/Date|From - To|Flight|Departs Arrives/拆分为多个文件

$0 - 指向标题(包含列名称)行(例如Date

gsub(/^ +| +$/, "", $0); - 将从每个标题行中删除所有尾随空格(例如“Flight”)

fn=gensub(/[ -]+/, "-","g",$0); - 用一个短划线替换多个空格/短划线以获得更合适的文件名。为fn变量分配了文件名

print $0 > "/tmp/"fn; - 将标题/模式行打印到相应的文件中(例如。Date行将写入/tmp/Date文件)

print > "/tmp/"fn; - 将所有后续记录写入相应的文件,直到下一个模式出现。

最终,我们将获得以下文件: /tmp/Date/tmp/From-To/tmp/Flight/tmp/Departs-Arrives

现在,我们可以合并和格式化我们的文件,使用pr命令按列打印它们:

pr -t -m -w 100 -s"|" /tmp/Date /tmp/From-To /tmp/Flight /tmp/Departs-Arrives

输出:

Date            |From - To               |Flight          |Departs Arrives
29-Jun-17       |Sydney - Beijing        |EK174           |19:40 05:30 (30-Jun-17)
05-Jul-17       |Beijing - Frankfurt     |EK931           |14:00 18:15
12-Aug-17       |Frankfurt - Shanghai    |EK736           |20:00 13:05 (13-Aug-17)
13-Aug-17       |Shanghai - Sydney       |EK175           |19:35 08:10 (14-Aug-17)

要了解更多abount pr命令:http://www.tutorialspoint.com/unix_commands/pr.htm

答案 1 :(得分:0)

看到通过预先实现的文本转换显然没有标准解决方案存在,这里有一个用Python做的版本。输入在文件series.txt中给出,输出写入table.txt,每个列中的行数被硬编码为此示例为row_num = 5

import csv

with open('series.txt', 'r') as inpfile:
    lines = inpfile.read().splitlines()
row_num = 5
# distribute to columns
cols = []
idx = 0
for l in lines:
    if idx == 0:
        cols.append([])
        idx = row_num

    cols[-1].append(l)
    idx -= 1;
# output columns
with open('table.txt', 'w') as csvfile:
    csvwriter = csv.writer(csvfile)
    for idx in range(0,row_num):
        out = ['{:<25}'.format(col[idx]) for col in cols]
        csvwriter.writerow(out)