首页 > 解决方案 > 根据字符串的出现对列重新编号

问题描述

对linux相当陌生,我很抱歉。

我有一个这样的文件:

1   C   foo   C     bar
2   C   foo   C     bar
3   C   foo   C     bar
4   H   foo   H     bar
5   H   foo   H     bar
6   O   foo   O     bar

我需要让它成为:

1   C01 foo   C     bar
2   C02 foo   C     bar
3   C03 foo   C     bar
4   H01 foo   H     bar
5   H02 foo   H     bar
6   O01 foo   O     bar

**不幸的是,必须保持 foo 和 C 之间的间距以及 C 和 bar 之间的间距。

我以分段方式进行了尝试,其中我提取了包含不同标识符 C、H 和 O 的行,并将它们放在临时文件中。然后我尝试按发生顺序对它们进行排序,然后将原始文件重新拼接在一起。

    #!/bin/bash

    sed -i -e "/ C /w temp1.txt" -e "//d" File.txt
    sed -i -e "/ H /w temp2.txt" -e "//d" File.txt
    sed -i -e "/ O /w temp3.txt" -e "//d" File.txt


    `awk -i '{print NR $2}' temp1.txt
    awk -i '{print NR $2}' temp2.txt
    awk -i '{print NR $2}' temp3.txt

    cat temp1.txt >> File.txt
    cat temp2.txt >> File.txt
    cat temp3.txt >> File.txt

但是我很确定我的语法很糟糕,因为我真的只熟悉 sed 而不是 awk。

任何帮助将不胜感激,谢谢。

标签: awksedseq

解决方案


编辑:awk这是一个保留实际空间的 GNU 解决方案如果您split支持 4 个参数。阅读手册页后,我得到了它,即使我很高兴找到它,它也会有所帮助。

awk '
{
  n=split($0,array," ",b)
  array[2]=sprintf("%s%02d",array[2],++a[array[2]])
  line=b[0]
  for(i=1;i<=n;i++){
    line=(line array[i] b[i])
  }
  print line
}'  Input_file
1   C01   foo   C     bar
2   C02   foo   C     bar
3   C03   foo   C     bar
4   H01   foo   H     bar
5   H02   foo   H     bar
6   O01   foo   O     bar

关于splitGNUawk手册页中的 4 个参数:

   split(s, a [, r [, seps] ])
                           Split the string s into the array a and the separators array seps on the regular expression r, and return the

字段数。如果省略 r,则使用 FS。首先清除数组 a 和 seps。seps[i] 是由 r 在 a[i] 和 a[i+1] 之间匹配的字段分隔符。如果 r 是单个空格,则 s 中的前导空格进入额外数组元素 seps[0],尾随空格进入额外数组元素 seps[n],其中 n 是 split(s, a , r, seps)。拆分的行为与上述的字段拆分相同。



第一个解决方案:您能否尝试以下操作,

awk '{$2=sprintf("%s%02d",$2,++a[$2])} 1' Input_file

输出如下。

1 C01 bar C
2 C02 bar C
3 C03 bar C
4 H01 bar H
5 H02 bar H
6 O01 bar O

第二种解决方案:如果您想在两个地方都有 $2 和 $4 的值,请执行以下操作。

awk '{$2=$4=sprintf("%s%02d",$2,++a[$2])} 1'  Input_file
1 C01 bar C01
2 C02 bar C02
3 C03 bar C03
4 H01 bar H01
5 H02 bar H02
6 O01 bar O01

第三种解决方案:如果您想在最后一行添加/插入新列,请执行以下操作。

awk '{$(NF+1)=sprintf("%s%02d",$2,++a[$2])} 1'  Input_file
1 C bar C C01
2 C bar C C02
3 C bar C C03
4 H bar H H01
5 H bar H H02
6 O bar O O01

推荐阅读