匹配到正向前瞻断言的第一个实例

时间:2015-09-21 04:43:18

标签: ruby regex

我为Fountain制作了一个Ruby解析器,这是一个类似于降序的纯文本语法,适用于剧本。这是一种不符合我希望的模式。我的模式是:后跟*markdown-style-emphasis*的东西。我想在第一次强调实例之前用它来提取东西

pattern = /(.+)(?=(?:\*.+\*))/
  • 以下输出nil因为没有匹配;积极的前瞻性断言是不满意的。没关系。

    pattern.match("hello")
    
  • 以下输出hello。它给了我一切,直到强调。这就是我想要的。

    pattern.match("hello *world*")[1]
    
  • 以下输出hello *world*。积极的前瞻断言是满意的,因为有些东西后面跟着一些降价式强调,但这些东西包括降价式强调。我希望它会被第一个实例所满足,但事实并非如此。有谁知道解决这个问题的方法?

    pattern.match("hello *world* *lol*")[1]
    

我试图将积极的前瞻性和消极的后瞻性结合起来表达任何事情,然后强调之前没有强调,但我不认为这种方法是可行的,因为看起来 - 后台只能在固定长度模式上断言。必须有办法做到这一点,对吗?

我推出了一个工作类型here,其中一个测试标记为待审xit

编辑(测试now感谢您的所有帮助,谢谢:))

2 个答案:

答案 0 :(得分:5)

你可能会让你的正则表达不贪心:

#             ⇓
pattern = /(.+?)(?=(?:\*.+\*))/

puts pattern.match("hello *world* *lol*")[1]
#⇒ "hello "

对于这种特殊情况,我会使用ruby predefined global $`

pattern = /\*.+\*/ # match whatever is to be actually matched
#⇒ /\*.+\*/
▶ pattern.match("hello *world* *lol*")
#⇒ nil
▶ puts $`  #` c’mon, parser
#⇒ "hello "

在我看来,这更具语义性。

答案 1 :(得分:3)

@ mudasobwa的第二个答案是最直截了当的。

关于第一个答案,这是一种方法,但另一种(更有效的方式)是使用[^*]。除此之外,你还有冗余的括号(捕获)会降低匹配速度。

pattern = /[^*]+(?=\*.+\*)/
pattern.match("hello")
# => nil
pattern.match("hello *world*")[0]
# => "hello "
pattern.match("hello *world* *lol*")[0]
# => "hello "