【问题标题】:Regex replace on specific column with SED/AWK正则表达式用 SED/AWK 替换特定列
【发布时间】:2015-03-17 04:07:40
【问题描述】:

我的数据看起来像这样(TAB 分隔):

Organ K     ClustNo Analysis
LN    K200  C12     Gene Ontology
LN    K200  C116    Gene Ontology
CN    K200  C2      Gene Ontology

我想要做的是为第三列上的每一行删除C,除了标题行:

Organ K     ClustNo Analysis
LN    K200  12      Gene Ontology
LN    K200  116     Gene Ontology
CN    K200  2       Gene Ontology

这不行,因为它会影响其他列和标题行:

sed 's/C//'

正确的做法是什么?

【问题讨论】:

    标签: linux unix awk sed


    【解决方案1】:

    使用 awk

    awk 是一个很好的工具:

    $ awk -F'\t' -v OFS='\t' 'NR>=2{sub(/^C/, "", $3)} 1' file
    Organ   K       ClustNo Analysis
    LN      K200    12      Gene Ontology
    LN      K200    116     Gene Ontology
    CN      K200    2       Gene Ontology
    

    工作原理

    • -F'\t'

      使用制表符作为输入的字段分隔符。

    • -v OFS='\t'

      使用制表符作为输出的字段分隔符

    • NR>=2 {sub(/^C/, "", $3)}

      仅针对第一行之后的行从字段 3 中删除初始 C。

    • 1

      这是 awk 对 print-the-line 的神秘简写。

    使用 sed

    $ sed -r '2,$ s/(([^\t]+\t+){2})C/\1/' file
    Organ   K       ClustNo Analysis
    LN      K200    12      Gene Ontology
    LN      K200    116     Gene Ontology
    CN      K200    2       Gene Ontology
    
    • -r

      使用扩展的正则表达式。 (在 Mac OSX 或其他 BSD 平台上,请改用-E。)

    • 2,$ s/(([^\t]+\t){2})C/\1/

      此替换仅适用于从 2 到文件末尾的行。

      (([^\t]+\t){2}) 匹配前两个制表符分隔的列。这假定只有一个选项卡分隔每一列。因为正则表达式包含在括号中,所以它匹配的内容稍后将作为\1 提供。

      C 这场比赛C。

      \1 仅将匹配的文本替换为前两列,而不是 C..

    【讨论】:

    • 谢谢。我们不能使用except first,因为第二列之后的其他列可能包含C。实际上不止 4 列。
    • 它是制表符分隔的。如何修改您的代码?
    • 制表符分隔很重要。你应该在前面说。我会做出一些改变。
    猜你喜欢
    • 2021-12-31
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多