【问题标题】:Merge Two files of columns but insert columns of second file into columns of first file合并两个列文件,但将第二个文件的列插入第一个文件的列
【发布时间】:2021-01-08 13:33:42
【问题描述】:

假设两个文件的列数相同。

file_A:

1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

file_B:

A B C D E
A B C D E
A B C D E
A B C D E
A B C D E

我想按顺序合并两个文件

file_C:

1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E
1 A 2 B 3 C 4 D 5 E

我在社区中找到了这样的解决方案

paste file_A file_B | awk '{print $1,$6,$2,$7,$3,$8,$4,$9,$5,$10}'

但是考虑到每个文件的列数是 100 或者不是恒定的,我想知道是否有更好的方法。

提前致谢。

【问题讨论】:

    标签: linux unix join merge multiple-columns


    【解决方案1】:

    paste 之后使用这个 Perl 单行来打印交替列:

    paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) /  2 ];'
    

    例子:

    创建制表符分隔的输入文件:

    perl -le 'print join "\t", 1..5 for 1..2;' > file_A
    perl -le 'print join "\t", "A".."E" for 1..2;' > file_B
    head file_A file_B
    

    打印:

    ==> file_A <==
    1       2       3       4       5
    1       2       3       4       5
    
    ==> file_B <==
    A       B       C       D       E
    A       B       C       D       E
    

    并排粘贴文件,也用制表符分隔:

    paste file_A file_B | perl -F'\t' -lane 'print join "\t", @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) /  2 ];'
    

    打印:

    1       A       2       B       3       C       4       D       5       E
    1       A       2       B       3       C       4       D       5       E
    

    Perl 单行程序使用这些命令行标志:
    -e:告诉 Perl 查找内联代码,而不是在文件中。
    -n:循环输入一行一次,默认将其分配给$_
    -l:在执行内联代码之前剥离输入行分隔符(默认为 *NIX 上的"\n"),并在打印时附加它。-a :在空格或-F 选项中指定的正则表达式上将$_ 拆分为数组@F
    -F'/\t/' :在TAB 上拆分为@F,而不是在空白上。

    $#F:数组 @F 的最后一个索引与输入字段,在选项卡上拆分。
    0 .. ( $#F - 1 ) / 2:数组 @F索引 数组,来自start (0) 到数组的一半。这些都是与file_A对应的索引。
    map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2map将上述索引数组从0到@F长度的一半,并返回一个新数组,其数量是两倍元素。它的元素交替出现:(a) 对应于 file_A 的索引 ($_) 和 (b) 该索引加上数组长度的一半 ($_ + ( @F/2 )),这是来自 file_B 的对应索引。
    @F[ map { ( $_, $_ + ( @F/2 ) ) } 0 .. ( $#F - 1 ) / 2 ] :具有指定索引的数组@F 的切片,即来自file_Afile_B 的交替字段。

    另请参阅:

    perldoc perlrun: how to execute the Perl interpreter: command line switches
    perldoc perldata: Slices

    【讨论】:

      【解决方案2】:

      你可以在awk中使用循环,例如

      paste file_A file_B | awk '{ 
          half = NF/2; 
          for(i = 1; i < half; i++)
          {
              printf("%s %s ", $i, $(i+half));
          }
          printf("%s %s\n", $half, $NF);
      }'
      

      paste file_A file_B | awk '{ 
          i = 1; j = NF/2 + 1;
          while(j < NF)
          {
              printf("%s %s ", $i, $j);
              i++; j++;
          }
          printf("%s %s\n", $i, $j);
      }'
      

      代码假设awk的输入中的列数是偶数。

      【讨论】:

        【解决方案3】:

        用一个 awk 脚本解析文件:

        FNR==NR {
            rec[NR] = $0
            next
        }
        
        {
            split(rec[FNR], fields)
            for (i=1;i<=NF;i++) $i = fields[i] FS $i
            print
        }
        

        用法:

        awk -f tst.awk file_A file_B
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-16
          • 1970-01-01
          • 1970-01-01
          • 2014-05-01
          • 2014-05-24
          • 2011-05-03
          • 1970-01-01
          相关资源
          最近更新 更多