繁体   English   中英

在bash中合并一个矩阵中的header列

[英]Merge header columns in a matrix in bash

我想合并矩阵的标题:

    12  12  12  13
bb  2   
cc      1               
aa          5
ee              6

像这样:

        12     13
bb      2        
cc      1        
aa      5        
ee              6

我试过这个但它没有用(它实际上不适用于更大的矩阵:

merged_headers=()
for i in {1..3}; do
    header=$(head -1 unmerge.txt | awk -v col=$i '{print $col}')
    if [ -z "$header" ]; then
        header=${merged_headers[-1]}
    else
        merged_headers+=($header)
    fi
    sed -i "s/^[ \t]*$/$header/g" unmerge.txt
done

假设:

  • 列按从左到右的顺序合并
  • 如果列标题是13 12 14 12 13 14那么新的列标题将是(从左到右) 13 12 14 (与生成12 13 14的数字或字符串排序相反)
  • 合并数据集每个唯一列最多有一个非空值 header; 否则,我们会将 append 它们组合成一个字符串; 如果保证多个值是数字,我们可以修改代码以对值求和

一个awk想法:

awk '
BEGIN { FS=OFS="\t"
        newcolno=1
      }
      { printf "%s", $1                                       # print 1st column

        if (NR==1) {                                          # if header record ...
           for (old=2; old<=NF; old++) {                      # loop through columns ...
               if (! ($old in newcol)) {                      # looking for new header and if found ...
                  printf "%s%s", OFS, $old                    # print to stdout and ...
                  newcol[$old]= ++newcolno                    # make note of the new column number to map to
               }
               old2new[old]= newcol[$old]                     # map current column number to new column number
           }
        }
        else {                                                # non-header rows
           delete row                                         # clear our new output array

           for (old=2; old<=NF; old++)                        # loop through current columns ...
               row[old2new[old]]=row[old2new[old]] $old       # append value to new row/column

           for (new=2; new<=newcolno; new++)                  # loop through new row/columns and ...
               printf "%s%s", OFS, row[new]                   # print to stdout
        }

        print ""                                              # terminate current line
      }
' unmerge.txt

这会产生:

        12      13
bb      2
cc      1
aa      5
ee              6

测试一个更大的文件来证明我们的一些假设:

$ cat unmerge2.txt
        12      12      12      13      12      13
bb      2
cc              1
aa                      5
ee                              6
ff                              17      87                # distinct headers so no problems
gg                              100             -3        # both have header "13" so we'll append the strings

awk脚本生成:

        12      13
bb      2
cc      1
aa      5
ee              6
ff      87      17
gg              100-3

一旦 OP 对结果感到满意,并假设 OP 仍想用新结果更新/覆盖输入文件:

  • 如果使用GNU awk ,您可以添加-i inplace inplace 以促进输入文件的就地更新: awk -i inplace 'BEGIN {FS=OFS="\t"; newcolno=1}...' unmerge.txt awk -i inplace 'BEGIN {FS=OFS="\t"; newcolno=1}...' unmerge.txt
  • 否则 OP 可以将 output 指向 tmp 文件,然后用 tmp 文件覆盖源文件: awk 'BEGIN {FS=OFS="\t"; newcolno=1}...' unmerge.txt > tmpfile; mv tmpfile unmerge.txt awk 'BEGIN {FS=OFS="\t"; newcolno=1}...' unmerge.txt > tmpfile; mv tmpfile unmerge.txt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM