如何将逗号分隔的字段分成单独的行

如何将逗号分隔的字段分成单独的行

输入文件:

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;

https://raku.org

相关内容