【问题标题】:Can we use conditionals based on lookbehinds?我们可以使用基于lookbehinds的条件吗?
【发布时间】:2018-12-20 22:29:51
【问题描述】:

我有一个正则表达式,其任务与此类似。这个人想要查找价格 (demo),其中美元符号必须在数字之前或之后,但不能两者兼而有之。

  \b       # "word" boundary
  (?<=\$)  # Assert that current position is preceded by $
  \d+\b    # digits, boundary
  (?!\$)   # Assert that current position is not followed by $
|          # alternation
  \b       # boundary
  (?<!\$)  # Assert that current position not preceded by $
  \d+\b    # digits, boundary
  (?=\$)   # Assert that current position is followed by $

PCRE 中有没有一种方法可以使用条件来对条件进行类似操作。 (demo)

(                 # capture 1, because we can't quantify lookarounds
  (?<=\$)         # Asserts that $ precedes current position
)?                # close capture 1, make it "optional" (0 or 1 times)

\b                # boundary
\d+               # digits
\b                # boundary
(?(1)             # conditional that capture #1 was a success
  (?!\$)          # if successful, assert that it is not followed by a #
|
  (?=\$)          # unsuccessful, assert that this position is followed by a $
)

注意:单词边界很重要,因此两者都要捕获整数,否则正则表达式会后退一步,从多位数字中剪掉一个数字。

上面的两个表达式都匹配 $15 和 16$,但不是 $17$,因为它们应该匹配。如果没有边界,它们将匹配 17 美元中的 15 美元、16 美元和 1 美元。

【问题讨论】:

    标签: regex pcre


    【解决方案1】:

    一个可行的解决方案 (demo)。问题的解决方法是 99 步,在这个简单的例子中是不必要的牺牲。在某些情况下,牺牲(如果有的话)是非常谨慎的。

    这最终变得非常简单。使捕获组 1拥有。这意味着无论它捕获什么,如果正则表达式试图回溯,它都不会投降。这意味着一旦它决定数字应该以$ 开头,如果数字后面也跟着$,它将不会让正则表达式回溯。它会放弃并继续前进,找到下一个边界,然后是数字并查看其周围环境。

    (                 # capture 1, because we can't quantify lookarounds
      (?<=\$)         # Asserts that $ precedes current position
    )?+               # close capture 1, make it "optional" (0 or 1 times)
                      # the possessive quantifier is the only change to the regex
                        # + is only 'possessive' when it's the second character of a quantifier
    
    \b                # boundary
    \d+               # digits
    \b                # boundary
    (?(1)             # conditional that capture #1 was a success
      (?!\$)          # if successful, assert that it is not followed by a #
    |
      (?=\$)          # unsuccessful, assert that this position is followed by a $
    )
    

    【讨论】:

    • 我看到完成输入字符串的任务需要 99 个步骤,而不是 66 个。
    • @revo 不错。我最初的测试没有第四个纯行,也没有第五个意外空白行。哎呀。
    • 为什么需要lookbehinds和条件构造?会有更优化的方法来做到这一点。
    猜你喜欢
    • 2019-06-01
    • 2022-12-15
    • 2015-03-21
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 2021-02-17
    相关资源
    最近更新 更多