文本处理块的行到列

文本处理块的行到列

我有一个包含 Solaris 上的列表的文件:

List A
hi
hello
hw r u

List B
Hi
Yes

List C
Hello

我需要转置列表,如下所示:

List A    List B    List C
hi        Hi        Hello
hello     Yes
hw r u

我如何在 Solaris 上执行此操作?

答案1

您可以awk将每个块拆分为单独的文件,然后paste将它们放在一起(下面假设每个列表之间始终有空行)。

awk '/^$/ {N++;next}{print >"file"N}' infile.txt
paste file*

您也可以将paste命令移至awk.

awk '/^$/ {N++;next}{print >"file"N} END{system("paste file*")}' inile.txt

输出是:

List A    List B    List C
hi        Hi        Hello
hello     Yes
hw r u

当改变线条长度时,结果会产生美丽的缩进,如下所示:

输入文件:

list A
hi
hello
hw r u

List B
Hi this is list B
Yes

List C
Hello, this is list C

你可以做paste file* |column -s $'\t' -tn并会得到结果:

list A  List B             List C
hi      Hi this is list B  Hello, this is list C
hello   Yes
hw r u

答案2

除了我之前的回答,还有csplit命令以相同的方式分割文件,然后使用paste命令获得所需的输出。

csplit -zs -f outputfile inputfile '/^List/' '{*}'
paste outfile*
  • '/^List/'是一个模式,用于匹配并将文件分解为下一个新文件
  • '{*}'尽可能多地重复该模式
  • -z用于删除空的输出文件;用于-s不打印输出文件大小的计数
  • -f用于定义自定义前缀输出文件##其中##默认为 2 位数字,您可以使用-n N(N 是定义的前缀后后缀中的数字位数)来定义它

答案3

GNUawk方法:

awk 'BEGIN{ max=0 }
     /^List/{ if(k && k>max) { max=k; idx=c } ++c; k=0 }
     NF{ a[c][++k]=$0 }
     END{ 
         for(i=1;i<=max;i++) 
             for(j=1;j<=c;j++) printf "%s%s",a[j][i],(j==c)?ORS:"\t" 
     }' file | column -ts$'\t'

输出:

List A  List B  List C
hi      Hi      Hello
hello   Yes
hw r u

答案4

命令

for i in "List A" "List B" "List C"; do sed -n "/$i/,/^$/p" h.txt >"$i.txt"; done

paste List\ *

输出

List A  List B  List C
hi  Hi  Hello
hello   Yes 
hw r u      

相关内容