【问题标题】:Regex query to print required output正则表达式查询以打印所需的输出
【发布时间】:2014-08-08 15:21:33
【问题描述】:

我有以下输入

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)" 

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

【问题讨论】:

    标签: regex bash unix scripting grep


    【解决方案1】:

    在 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。

    带有 Lookarounds 的备用正则表达式

    既然你正在学习正则表达式......这也有效。

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

    参考

    The Many Degrees of Regex Greed

    【讨论】:

    • FYI 的扩展是什么?
    • @AvinashRaj 仅供参考,FYI 的扩展是“供您参考”。 :)
    • 仅供参考添加了对您的模式有什么问题的解释。 :)
    • @user1377135 不客气,下次见。 :)
    • 但是您的第一个命令显示text1,2,3,4。 op 只想要text1,2,4
    【解决方案2】:

    使用sed -r:

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

    PS:在 OSX 上使用sed -E。

    【讨论】:

    • op 希望输出为text1,2,4
    【解决方案3】:

    还有一个通过 awk,

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      • 1970-01-01
      • 2014-05-03
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多