Perl 如何解析TSV中移位的空列?

Perl 如何解析TSV中移位的空列?,perl,sed,awk,Perl,Sed,Awk,我有一个要解析的TSV文件。所有列中都有空字段,导致列的顺序发生位移,因此我使用特定列号获得的值实际上并非全部来自该列 某些字段包含长字符串,其中包含空格。此外,有些列包含潜在的分隔符,如|: 输入文件 columnA columnB columnC columnD A1 B1 C1 D1 B2 C2 D2 A3 D3 A4 B4 D

我有一个要解析的TSV文件。所有列中都有空字段,导致列的顺序发生位移,因此我使用特定列号获得的值实际上并非全部来自该列

某些字段包含长字符串,其中包含空格。此外,有些列包含潜在的分隔符,如
|

输入文件

 columnA    columnB    columnC    columnD
 A1         B1         C1         D1
 B2         C2         D2    
 A3         D3
 A4         B4         D4
期望输出

 columnA    columnB    columnC    columnD
 A1         B1         C1         D1
            B2         C2         D2    
 A3                               D3
 A4         B4                    D4
$file myfile

`ASCII English text, with very long lines` 
$awk'-F\t'{print NF}'myfile | sort | uniq-c | tail-n

`247871 136`
我在回复类似问题()时发现了此代码,但我的文件无法使用此代码:

sed ':x s/\(^\|\t\)\t/\1 \t/; t x' < file.tsv | column -t -s $'\t'
sed':xs/\(^\\t\)\t/\1\t/;t x'
(导入Excel后问题仍然存在。)

如果使用了更多的列,则应使用迭代方式(与test/“insert”的概念相同)

在我的AIX/KSH上(因此应该与GNU上的
--posix-e
相同)


如果文件是以制表符分隔的,则应在
awk
中使用制表符作为字段分隔符。像

$ column -t -s $'\t' file

columnA  columnB  columnC  columnD
A1 1     B1 2     C1 3     D1 4
B2 2     C2 4     D2 4
A3 1     D3 4
A4 1     B4 2     D4 4

$xxd file
0000000: 636f 6c75 6d6e 4109 636f 6c75 6d6e 4209  columnA.columnB.
0000010: 636f 6c75 6d6e 4309 636f 6c75 6d6e 440a  columnC.columnD.
0000020: 4131 2031 0942 3120 3209 4331 2033 0944  A1 1.B1 2.C1 3.D
0000030: 3120 340a 0942 3220 3209 4332 2034 0944  1 4..B2 2.C2 4.D
0000040: 3220 340a 4133 2031 0909 0944 3320 340a  2 4.A3 1...D3 4.
0000050: 4134 2031 0942 3420 3209 0944 3420 340a  A4 1.B4 2..D4 4.

$ awk -F'\t' '{
    for (i=1; i<=NF; i++) {
        printf "%-8s ", $i
    }
    print ""
}'

columnA columnB columnC columnD 
A1 1    B1 2    C1 3    D1 4    
        B2 2    C2 4    D2 4    
A3 1                    D3 4    
A4 1    B4 2            D4 4 
$column-t-s$'\t'文件
A列B列C列D
A1 1 B1 2 C1 3 D1 4
B2 2 C2 4 D2 4
A3 1 D3 4
A4 1 B4 2 D4 4
$xxd文件
0000000:636f 6c75 6d6e 4109 636f 6c75 6d6e 4209 columnA.columnB。
0000010:636f 6c75 6d6e 4309 636f 6c75 6d6e 440a列C列D。
0000020:4131 2031 0942 3120 3209 4331 2033 0944 A1 1.B1 2.C1 3.D
0000030:3120340A 0942 3220 3209 4332 2034 0944 14..B2 2.C2 4.D
0000040:3220340A 4133 2031 0909 0944 3320 340a 2 4.A3 1…D3 4。
0000050:4134 2031 0942 3420 3209 0944 3420 340a A4 1.B4 2..D4 4 4。
$awk-F'\t''{

对于(i=1;i如果将其加载到Excel中会发生什么情况?列仍会被替换。此外,列数约为200,行数为250K。我建议组合使用
expand
将选项卡转换为空格,然后使用固定字段大小的
awk
——类似于
expand。您必须手动使用<<代码> AWK</代码>中的尾随空格,使用<代码> GSUB/CODE >或某些东西……但是,尽管在您的示例中,我不确定您应该如何能够知道D3属于第四列,而不是第二列或第三列……考虑使用该CMD的输出使用您的实际文件编辑您的帖子。code>awk'-F\t'{print NF}'bigFile | sort | uniq-c | tail-5
。如果您有一个格式良好的制表符分隔文件,您应该只得到一行输出。如果得到的行数超过一行,则可以查看计数是否有规律性。(不要害怕将
tail-5
更改为
tail-50
或其他数字)。有没有可能这是一个更大的分为多行的行?最后,如果文件源是Windows,并且您在Linux中工作,请不要忘记
dos2unix bigFile
。祝您好运。这证明没有记录缺少字段。字段中可能没有任何数据,因此我希望找到N个数字制表符ajo在缺少数据的情况下,使用
awk'-F\t'-v OFS=“\t”{print$9、$12、$15、$18}文件
(例如)应该会给你一致的结果。祝你好运。我对sed非常陌生,如果我的问题非常基本,那么很抱歉。首先,我无法让你的代码用于示例文件。我在ubuntu上。我以你编写的形式和
sed--posix-e“…”都试过了YourFile
。根据您对
字段空的定义,我想我的实际数据可能会有问题,因为某些列的单元格内容中包含空格。非常感谢!是否有错误消息或只是数据输出不符合要求?在bash中,我得到了这一点(有或没有
--posix-e
):
sed:-e expression#1,char 1:未知命令:
“`try可能将内容放在文件中的
之间,并使用
-f
后跟文件名来代替
-e”。。。"
您能解释一下如何运行
xxd文件
吗?我应该保存输出并在其上运行
awk
代码吗?在您的回答中,字段中的单个数字是用于演示的吗?谢谢!@user2162153是的,这些数字只是用于演示,因此您可以看到它们里面有空格。请将
文件
替换为h您的文件(
myfile
)@user2162153
xxd
仅用于演示。它显示输入文件包含作为分隔符的选项卡。选项卡的十六进制代码为
09
。谢谢。它对我的数据不起作用。由于我不确定示例文件的格式是否与真实文件的格式相同,我不能说它不起作用。解决方案是:正如下面的评论所述,这篇文章(底部第三篇)解决了这个问题。我感谢你的帮助。
$ cat YourFile
 columnA    columnB    columnC    columnD
 A1         B1         C1         D1
 B2         C2         D2
 A3         D3
 A4         B4         D4
$ FieldEmpty='           ';FieldSize=${#FieldEmpty};echo $FieldSize
11
$sed "..." YourFile
 columnA    columnB    columnC    columnD
 A1         B1         C1         D1
            B2         C2         D2
 A3                               D3
 A4         B4                    D4
$ column -t -s $'\t' file

columnA  columnB  columnC  columnD
A1 1     B1 2     C1 3     D1 4
B2 2     C2 4     D2 4
A3 1     D3 4
A4 1     B4 2     D4 4

$xxd file
0000000: 636f 6c75 6d6e 4109 636f 6c75 6d6e 4209  columnA.columnB.
0000010: 636f 6c75 6d6e 4309 636f 6c75 6d6e 440a  columnC.columnD.
0000020: 4131 2031 0942 3120 3209 4331 2033 0944  A1 1.B1 2.C1 3.D
0000030: 3120 340a 0942 3220 3209 4332 2034 0944  1 4..B2 2.C2 4.D
0000040: 3220 340a 4133 2031 0909 0944 3320 340a  2 4.A3 1...D3 4.
0000050: 4134 2031 0942 3420 3209 0944 3420 340a  A4 1.B4 2..D4 4.

$ awk -F'\t' '{
    for (i=1; i<=NF; i++) {
        printf "%-8s ", $i
    }
    print ""
}'

columnA columnB columnC columnD 
A1 1    B1 2    C1 3    D1 4    
        B2 2    C2 4    D2 4    
A3 1                    D3 4    
A4 1    B4 2            D4 4