我有一个包含 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