【问题标题】:A multi-line, variedly greedy, regular expression一个多行、多变贪婪的正则表达式
【发布时间】:2014-11-21 22:19:32
【问题描述】:

鉴于以下文本,您会使用什么 PCRE 正则表达式来提取粗体标记的部分?

00:20314 lorem ipsum 想要这个 氪石 00:02314 qux 填充 不想要这个 00:03124 富 这也不是 00:01324 富 但我们想要这个 石笋 00:02134 特拉拉拉 不是这个 00:03124 bar foo 我们想要这个 氪石 但不是这个(!) 00:02134 富吧 而不是这个 00:01234 dolor sit amet EOF

IOW,我们想要提取以正则表达式开头以“^0”开头并以“(kryptonite|stalagmite)”结尾的部分。

一直在咀嚼这个,发现它很难破解。蒂亚!

【问题讨论】:

  • 有几种方法可以做到这一点。分隔符可以在正文中吗?
  • 唯一的分隔符不需要正文中的其他^0

标签: regex pcre regex-greedy


【解决方案1】:

一种方法是 Negative Lookahead 与内联 (?sm) dotall and multi-line modifiers 结合使用。

(?sm)^0(?:(?!^0).)*?(?:kryptonite|stalagmite)

Live Demo

【讨论】:

    【解决方案2】:

    这看起来有效。

     # (?ms)^0(?:(?!(?:^0|kryptonite|stalagmite)).)*(kryptonite|stalagmite)
    
     (?ms)
     ^ 0
     (?:
          (?!
               (?: ^ 0 | kryptonite | stalagmite )
          )
          . 
     )*
     ( kryptonite | stalagmite )
    

    【讨论】:

    • 相同的概念,但您也包括关键字。不错 =)
    • 关键字可能不需要。你的更好。
    • 不过,想法相同 =) (+1)
    • 这是唯一的方法。
    【解决方案3】:

    我相信这将是最有效的:

    ^0(?:\R(?!\R)|.)*?\b(?:kryptonite|stalagmite)\b
    

    Demo


    显然,我们以^0 开头,然后以\b word boundaries 包围的kryptonitestalagmite(在一个非捕获组中)结束。

    (?:\R(?!\R)|.)*? 是有趣的部分,所以让我们分解一下。第一个关键概念是 PCRE 的\R newline sequence

    (?:      (?# start non-capturing group for repetition)
      \R     (?# match a newline character)
      (?!\R) (?# not followed by another newline)
     |       (?# OR)
      .      (?# match any character, except newline)
    )*?      (?# lazily repeat this group)
    

    【讨论】:

    • 你需要在你的表达式中添加$
    • @HamZa,我不这么认为:00:03124 bar foo and we want this kryptonite but not this(!)
    【解决方案4】:

    ^(00:.*?(kryptonite|stalagmite)) 带 s 修饰符

    【讨论】:

    • 根本不符合预期的输出
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 2013-02-15
    相关资源
    最近更新 更多