当模式与grep匹配时,保持线条结构

  • 本文关键字:结构 模式 grep grep
  • 更新时间 :
  • 英文 :


我有一个关于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]

有什么想法吗?如果任何人能提供任何见解,我将不胜感激。

$ 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]

我还将"|"移到了字符列表之外,因为它似乎不属于您发布的示例输入中的字符列表。

当您设置-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支持的任何正则表达式。与公认的答案不同,这种方法对于非空格分隔的regex不会失败,这可能非常重要。

最新更新