正则表达式查询打印所需的输出

时间:2014-06-18 10:53:33

标签: regex bash unix scripting grep

我有以下输入

ASR cAND text1 (p .Pro221Leu)
   GMPPB cAND text2 c .1069G> A(p.Val357Ile)
   KLHL40 cAND text3
   GMPPB cAND text4 c .220C> T(p.Arg74Ter)

我想在粗体之间打印任何文字,即 cAND 和((p c )之间的文字
   注意:text3不是预期的,因为它不能满足上述条件。

expected output(underlined) 
text1
text2
text4    

regex used
grep "cAND.+(c\.|\(p)" 

但是我没有得到预期的输出。请告诉我我的正则表达式有什么问题?谢谢

3 个答案:

答案 0 :(得分:4)

在Perl模式下使用grep,您可以执行此操作(请参阅demo):

grep -P "cAND[ ]*\K\S+(?=[ ]*(?:c.|\(p))" some_path_or_files

它是如何运作的?贪婪。

  • cAND[ ]*确保我们拥有cAND并且还匹配以下空格
  • \K会丢弃到目前为止我们匹配的内容,以便我们可以返回干净的字符串,例如text1
  • \S+匹配我们想要的字符:任何非空格字符
  • (?=[ ]*(?:c.|\(p))前瞻确保后面的内容是空格和c或p分隔符

出了什么问题?

  1. .+中的cAND.+(c\.|\(p)是“贪婪的”:它会占用所有字符,直到字符串结束,然后它会回溯直到(c\.|\(p)可以满足。因此,它会占用最后一个c或p的字符,例如:cAND text2 c.1069G>A (p
  2. 它匹配整个字符串,而不仅仅是text1
  3. 带有Lookarounds的备用正则表达式

    因为你正在研究正则表达式......这也有效。

    (?<=cAND).*?(?=c.|\(p)
    

    <强>参考

    The Many Degrees of Regex Greed

答案 1 :(得分:1)

使用sed -r

sed -r 's/^.*cAND ([^ ]+)( \(?[cp].*)?$/\1/' file
text1
text2
text3
text4

PS:在OSX上使用sed -E

答案 2 :(得分:0)

那个通过awk,

$ awk '$2=="cAND" && $4~/^c|^\(p/ { print $3}' file
text1
text2
text4

检查第2列为cAND,第4列是以c还是(p开头。如果满足两个条件,则将打印该对应行的第3列。