按标题将基于行的数据转换为列

时间:2014-11-06 14:46:14

标签: unix text file-handling

我有一个(相当大)的文件,格式如下:

SET1
A B C D E F G

SET2
H I J K L M

SETX
(...)

我更愿意拥有它们

SET1    SET2   SETX
A       H     (...)
B       I
C       J
D       K
E       L
F       M
G

请注意,列的长度不等,并且不按大小排序。我的文件太大了,无法使用内置在unix中的column函数,并且通过拼接文件然后将其粘贴在一起来尝试变得可爱已经产生了有问题的结果(也就是说,它导致空列变得相同内容作为分隔符,对我的目的不起作用 - 它们最终都是" \ t")。请注意,每个集合可能包含数百个条目,并且我有数千个集合,这使得awk不切实际(至少在那里我的技能有限)。

理想情况下,输出应该在R中可读,但此​​时我会非常高兴能够实际转换为R输入的内容。请注意,如果更实用,我可以完全使用非空白分隔符。

非常感谢您的任何帮助!在外部Linux环境中工作。

编辑: 我也有文件

SET1
A
B
C
D
E
F
G

SET2
H
I
J
K
L
M

如果这样可以更容易。

1 个答案:

答案 0 :(得分:2)

我想这更像是你想要的:

awk -v OFS="\t" 
    '/^SET/ {sets[++cols]=$0; set=$0; max_recs=(c>max_recs?c:max_recs); c=0; next}
     NF{a[cols,++c]=$0}

     END {
        for (i=1;i<=cols; i++) printf "%s%s", sets[i], OFS
        print ""
        for (i=1; i<=max_recs; i++) { 
            for (j=1; j<=cols; j++) printf "%s%s", a[j,i], OFS
            print ""
        }
     }' file

对于这个给定的输入:

SET1
B
C
D
E
F
G

SET2
H
I
J
K
L
M
AAA

SET3
A
B
C
D

它返回:

$ awk -v OFS="\t" '/^SET/ {sets[++cols]=$0; set=$0; max_recs=(c>max_recs?c:max_recs); c=0; next} NF{a[cols,++c]=$0} END {for (i=1;i<=cols; i++) printf "%s%s", sets[i], OFS; print ""; for (i=1; i<=max_recs; i++) { for (j=1; j<=cols; j++) printf "%s%s", a[j,i], OFS; print ""}}' file
SET1    SET2    SET3    
B   H   A   
C   I   B   
D   J   C   
E   K   D   
F   L       
G   M       
    AAA     

只有一个区块的先前解决方案。

您可以使用paste并排显示文件。

在这种情况下,让我们使用headtail来获得一半和一半。然后,xargs每行打印一个文本块。然后他们准备好paste d:

paste -d"\t" <(head -2 file | xargs -n1) <(tail -2 file | xargs -n1)

对于您的给定输入,它返回:

SET1    SET2
A       H
B       I
C       J
D       K
E       L
F       M
G