【问题标题】:Ruby 1.9 Regex Lookbehind Assertion & AnchorsRuby 1.9 正则表达式 Lookbehind Assertion & Anchors
【发布时间】:2010-08-02 20:25:39
【问题描述】:

Ruby 1.9 正则表达式支持后向断言,但在模式中传递锚点时我似乎遇到了困难。当在前瞻断言中传递锚点时,它运行得很好。

"well substring! "[/(?<=^|\A|\s|\b)substring!(?=$|\Z|\s|\b)/] #=> RegexpError: invalid pattern in look-behind: /(?<=^|\A|\s|\b)substring(?=$|\Z|\s|\b)/

有人知道如何使锚点在后向断言中像在前瞻中一样工作吗?

lookbehind 是否需要特殊的转义序列或分组?

我已经在 1.9.1-p243、p376 和 1.9.2-preview3 中测试了这种行为,以防它被修补。

【问题讨论】:

  • 最后,这不是一个锚问题,因为锚 \b 没有像前瞻断言那样被识别为单词边界。使用 Not a Not word 边界 - [^\B] 解决了问题。
  • 这可能会让人感到意外,但如果\b 在你身后,它也在你面前!对于所有零宽度锚点都是如此,至少在 Java 中是这样。
  • 克拉皮!世界这么小!

标签: regex anchor assertions ruby-1.9 lookbehind


【解决方案1】:

看起来你是对的:\b 在前瞻中按预期工作,但在后瞻中它被视为语法错误。

在这种情况下,这并不重要:如果(?&lt;=^|\A|\s|\b) 会产生所需的结果,那么无论如何,\b 就是您所需要的。断言后面的字符必须是s--一个单词字符--所以\b 意味着(1)前一个字符不是一个单词字符,或者(2)那里没有前一个字符。既然如此,^\A\s都是多余的。

但是,如果字符串以! 开头,那就是另一回事了。 ^\A 仍然匹配字符串的开头,before !,但 \b 匹配 after 它。如果你想匹配!substring!作为一个完整的字符串你必须使用/\A!substring!\Z/,但是如果你只想匹配整个单词substring你必须使用/\bsubstring\b/

对于[^\B],它只匹配除B 之外的任何字符。和\b 一样,\B 是一个零宽度断言,一个字符类必须精确匹配一个字符。一些正则表达式风格会为无效的转义序列 \B 抛出异常,但 Ruby(或 Oniguruma,更有可能)让它滑动。

【讨论】:

    【解决方案2】:

    看起来后向的解释是范围 [] 的解释,而不是像前瞻断言那样的组 ()。这可能意味着 \b 是无效的退格字符而不是单词边界。

    "well substring! "[/(?<=^|\A|\s|[^\B])substring!(?=$|\Z|\s|\b)/]  #=> substring!
    "well substring! "[/(?<=^|\A|\s|[^\B])substring(?=$|\Z|\s|\b)/]   #=> substring
    "well !substring! "[/(?<=^|\A|\s|[^\B])substring(?=$|\Z|\s|\b)/]  #=> substring
    "well !substring! "[/(?<=^|\A|\s|[^\B])!substring(?=$|\Z|\s|\b)/] #=> !substring
    

    当所有其他方法都失败时...使用双重否定!

    【讨论】:

      【解决方案3】:

      是的,看起来 Ruby 1.9.2 不支持 \b 并在后面看。

      ruby-1.9.2-p180 :034 > "See Jeffs book and it seems fine!".gsub(/(?=s\b)(?<=\bJeff)/,"'")
      SyntaxError: (irb):34: invalid pattern in look-behind: /(?=s\b)(?<=\bJeff)/
      from /home/pratikk/.rvm/rubies/ruby-1.9.2-p136/bin/irb:16:in `<main>'
      
      ruby-1.9.2-p180 :033 > "See Jeffs book and it seems fine!".gsub(/(?=s\b)(?<=Jeff)/,"'")
       => "See Jeff's book and it seems fine!" 
      

      【讨论】:

      • 它确实支持 \d 。 ruby-1.9.2-p180 :002 &gt; "298281974382".gsub(/(?=(\d\d\d)+$)(?&lt;=\d)/,",") =&gt; "298,281,974,382"
      • 那是因为 \d 只是一个像 [0-9] 这样的字符类。您可以在后视锚中包含字符类是有道理的,但将像 \b 这样的锚放在锚中可能没有多大意义(或无法解释)。
      猜你喜欢
      • 1970-01-01
      • 2012-07-23
      • 2012-02-08
      • 2021-05-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多