输入文件:
A B C D
1 2,3,4,5 6,7 8,9,10,11
输出文件:
A B C D
1 2 6 8
3 7 9
4 10
5 11
答案1
perl -MList::Util=max -lane '
@F = map {[split /,/]} @F;
$n = max map {scalar @$_} @F;
foreach $i (0..$n-1) {print join "\t", map {$_->[$i]} @F};
' file
答案2
使用 GNU datamash
,转置数据两次。第一次转置是使用空格作为输入分隔符并使用逗号作为输出分隔符来完成的。根据您在问题中的示例,这为我们提供了以下数据:
A,1
B,2,3,4,5
C,6,7
D,8,9,10,11
然后再次使用逗号作为输入和输出分隔符进行转置,同时关闭严格模式(记录不必具有相同数量的字段)并添加空格作为缺失字段。这导致
A,B,C,D
1,2,6,8
,3,7,9
,4, ,10
,5, ,11
然后运行结果以column
格式化为一个漂亮的表格,类似于您的问题:
A B C D
1 2 6 8
3 7 9
4 10
5 11
完整的命令管道:
datamash -W --output-delimiter=, transpose <file |
datamash -t , --filler=' ' --no-strict transpose |
column -s , -t
答案3
与awk
+ paste
:
awk '{
for(i=1; i<=NF; i++) {
gsub(",", "\n", $i); close("col_"i); print $i >>"col_"i
}
}' infile && paste col_*
笔记:
- 您可以稍后删除 awk 生成的临时文件
rm -f col_*
。\ - 您可能还想将
paste
命令输出传递给以|column -s $'\t' -tn
正确对齐列,请参阅分两列打印两个文件了解详情。
答案4
使用乐(以前称为 Perl_6)
raku -e 'lines[0].put; my @a; @a.push( $_.split(",")) for lines.split("\t"); \
my $i = @a>>.elems.max; my @b; for @a -> $a { for ^$i { \
@b[$++].push($a[$_] // "␀".Str)}}; \
$_.put for @b>>.join("\t");' file
或者
raku -e 'lines[0].put; my @a; @a.push: $_.split(",") for lines.split("\t"); \
my $i = @a>>.elems.max; my @b; for @a -> $a { \
@b[$++].push($a[$_] // "␀".Str) for ^$i }; \
put($_, "\t") for [Z] @b.rotor($i);' file
输入示例:
A B C D
1 2,3,4,5 6,7 8,9,10,11,12
示例输出(列分开\t
):
A B C D
1 2 6 8
␀ 3 7 9
␀ 4 ␀ 10
␀ 5 ␀ 11
␀ ␀ ␀ 12
上面是用 Raku(Perl 编程语言家族的成员)编写的解决方案。假设输入文本文件是两线文件,每行在\t
(可能有数百个)列之间用制表符分隔,用,
逗号分隔每列中存在的元素。
简而言之,第一行是put
标题行。数组@a
由后续行填充,首先按\t
制表符(表示列)拆分,然后按,
逗号拆分。@a
然后使用 计算数组的最长元素@a>>.elems.max;
。然后, 的元素@a
被复制到新声明的@b
数组中,但需要注意的是,Raku 的//
“定义-OR”运算符用于␀
在未定义的位置插入。 (该代码也适用于"".Str
空字符串)。最后,@b
数组数据被put
(打印)出来。
[输出中的列正确对齐。任何未对齐都是由于占位符字符的宽度造成的␀
]。
请注意,可以首先(单独)处理标题行,例如,如果它是空格分隔的:
my $header=lines[0].split("\s"); $header.join("\t").put;
或者(更简单)
lines[0].split("\s").join("\t").put;