【问题标题】:Keep line structure when pattern matching with grep使用 grep 进行模式匹配时保持行结构
【发布时间】:2016-04-21 04:18:59
【问题描述】:

我有一个关于 grep 的问题。我正在寻找多行文本中的特定模式。同一行通常有多个匹配项。我已经弄清楚如何提取我的模式,但是 grep 将每个匹配项放在一个新行上。有什么办法可以阻止 grep 这样做吗?理想情况下,我希望提取所有匹配项并保留原始文件的行结构。

这是一个例子:

一个输入行(其中有数千行):

MUC3A|ENST00000414964[in] MUC3A|ENST00000422757[in] MUC3A|ENST00000319509[in] MUC3A|ENST00000483133[in] RP11-395B7.2.1|ENST00000420080[me] RP11-395B7.2.1|ENST00000438198[me] RP11-395B7.2.1|ENST00000434775[5g] MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g] MUC3A|ENST00000480291[5g] 

我的 grep 命令:

grep -oe MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]

我目前的输出:

MUC12|ENST00000536621[5g]
MUC12|ENST00000379442[5g]

我的理想输出:

MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]

有什么想法吗?我将非常感谢任何人可以提供的任何见解。

【问题讨论】:

    标签: grep


    【解决方案1】:
    $ awk '{
       s=""
       for (i=1;i<=NF;i++) {
          if ($i ~ /MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]/) {
             printf "%s%s",s,$i
             s=" "
          }
       }
       print ""
    }' file
    MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]
    

    我会稍微更改您的 RE 以锚定表达式,使用字符类而不是显式范围以实现简洁和可移植性,并查找 1 个或多个字符 (+) 而不是允许零 (*):

    $ awk '{
       s=""
       for (i=1;i<=NF;i++) {
          if ($i ~ /^MUC12\|[[:alnum:]-]+\[[[:alnum:]]+\]$/) {
             printf "%s%s",s,$i
             s=" "
          }
       }
       print ""
    }' file
    MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]
    

    我也移动了“|”在字符列表之外,因为它似乎不属于您发布的示例输入。

    【讨论】:

    • @user2094907 - 不客气。如果/当您得到您接受的答案时,请记得点击它旁边的复选标记,以便阅读本文的人知道您得到了答案。
    【解决方案2】:

    当您设置-o 标志时,grep 将在新行上单独打印每个匹配项,并且无法更改此行为。简单的修复方法是让grep 打印出每场比赛的行号,然后加入连续编号的行。您可以使用awk 来执行此操作。像这样运行:

    < file grep -one "MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]" | awk -f script.awk
    

    script.awk的内容:

    BEGIN {
        FS=":"
    }
    
    $1 == y {
        sub(/[^:]+:/,"")
        r = (r ? r OFS : "") $0
        next
    }
    
    x {
        print x, r
        r=""
    }
    
    {
        x=$0
        y=$1
        sub(/[^:]+:/,"",x)
    }
    
    END {
        print x, r
    }
    

    或者,这里是单行:

    < file grep -one "MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]" | awk -F ":" '$1 == y { sub(/[^:]+:/,""); r = (r ? r OFS : "") $0; next } x { print x, r; r="" } { x=$0; y=$1; sub(/[^:]+:/,"",x) } END { print x, r }'
    

    这里介绍的方法可以应用于grep 支持的任何正则表达式。与公认的答案不同,这种方法不会因非空格分隔的正则表达式而失败 - 这可能非常很重要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 2011-04-02
      • 2022-12-14
      • 2022-12-19
      • 2013-02-27
      • 2013-04-05
      • 1970-01-01
      相关资源
      最近更新 更多