如何将制表符分隔文件中的行转置为列?

如何将制表符分隔文件中的行转置为列?

我有一个制表符分隔的文件,其中有一个数字,并且同一行上有属于同一个数字的名称。数字和名称由制表符分隔。名称通过 2 个下划线 ( ) 相互链接__。它看起来像这样:

33  Hhe.1__Hhe.2__Hhe.3__Hhe.4

我想将其(通过使用命令行)转换为以下输出:

33  Hhe.1
33  Hhe.2
33  Hhe.3
33  Hhe.4

答案1

awk

$ awk -F '\t|__' '{for (i=2;i<=NF;i++) {printf "%s\t%s\n", $1, $i}}' foo.txt 
33  Hhe.1
33  Hhe.2
33  Hhe.3
33  Hhe.4
  • \t我们根据制表符 ( ) 或两个下划线 ( )将行拆分为字段__
  • 然后我们循环从第二个字段到最后一个字段,并打印每个以第一个字段和制表符为前缀的字段。

答案2

您可以使用 perl 单行命令来实现这一点:

perl -ane '@l=split(/__/,$F[1]); foreach $val (@l){print $F[0],"\t",$val,"\n"}'

例子:

$ echo "33  Hhe.1__Hhe.2__Hhe.3__Hhe.4" | perl -ane '@l=split(/__/,$F[1]); foreach $val (@l){print $F[0],"\t",$val,"\n"}'
33  Hhe.1
33  Hhe.2
33  Hhe.3
33  Hhe.4

所用命令的解释:

perl -ane                    #read input line-wise and split line on tab
'@l=split(/__/,$F[1]);       #split the second element ($F[1]) on a double _
foreach $val (@l){           #for each value, print the first element and the value.
  print $F[0],"\t",$val,"\n"
 }'

答案3

另一种使用 Perl 的方法:

perl -lane '$,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])))' file
perl -lane '
    $,="\n";
    print(map($F[0] . "\t" . $_, split("__", $F[1])))
' file
  • -l[octnum]: 启用自动行结束处理。它有两个单独的效果。首先,当与或$/一起使用时,它会自动 chomps(输入记录分隔符)。其次,它分配(输出记录分隔符)以具有 octnum 的值,以便任何打印语句都会重新添加该分隔符。如果省略 octnum,则设置为 的当前值。-n-p$\$\$/
  • -a-n:与或一起使用时打开自动拆分模式-p。对数组的隐式拆分命令@F是 或 产生的隐式 while 循环中的第一-n件事-p
  • -n:导致 Perl 假设您的程序中存在以下循环,这使得它像sed -n或一样迭代文件名参数awk

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e:可用于输入一行程序;

  • $,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])));将输出字段分隔符设置为换行符,拆分第二个字段__并将第一个字段添加到每个子字段的前面,然后添加制表符,最后打印记录。
% cat file
33  Hhe.1__Hhe.2__Hhe.3__Hhe.4
% perl -lane '$,="\n"; print(map($F[0] . "\t" . $_, split("__", $F[1])))' file
33  Hhe.1
33  Hhe.2
33  Hhe.3
33  Hhe.4

答案4

与 muru 建议的类似:如何根据切片拆分第二个字段__,然后循环切片?

awk 'BEGIN{FS=OFS="\t"}
     {n=split($2,a,"__"); for (i=1;i<=n;i++) print $1, a[i]}' file

这利用了以下事实split()返回创建的元素的数量。

此外,它将输入和输出字段分隔符设置为制表符,这样您在输入时就不必提及它print。事实上,FS这里不需要设置,因为FS默认包含空格和制表符。

它返回:

33  Hhe.1
33  Hhe.2
33  Hhe.3
33  Hhe.4

相关内容