可以重新忽略惰性量词吗?

Can re ignore a lazy quantifier?

鉴于此代码 (Python 3.6):

>>> import re
>>> a = re.search(r'\(.+?\)$', '(canary) (wharf)')
>>> a
<_sre.SRE_Match object; span=(0, 16), match='(canary) (wharf)'>
>>>

为什么不在第一个括号闭包处重新停止搜索?

预期输出为 None。搜索应该检测到 (canary) 之后没有行尾 ,但它没有。

编辑:如果括号之间只有一个单词,则应该匹配,如果有多个单词,则根本不匹配。

如有任何帮助,我们将不胜感激。

惰性标志未被忽略。

你得到了整个字符串的匹配,因为 .+? 意味着匹配 任何东西 一次或多次,直到你找到一个匹配,根据需要扩展。如果 regex was \([^)]+?\)$ 它只会匹配最后一个 (wharf) 因为我们从匹配 )

中排除了 +?

或者如果正则表达式是 \(.+?\),它会匹配 (canary) (wharf),这表明它是惰性的.

\(.+?\)$ 匹配所有内容,因为您 使其 匹配所有内容,直到行尾。

如果你想确保整个字符串中括号中只有一组,我们可以用上面的“no-parentheses-regex”来做到这一点,并强制字符串的开头与你的正则表达式。

^\([^)]+?\)$
试一试:https://regex101.com/r/Ts9JeF/1

解释:

  • ^\(:在字符串
  • 的开头匹配文字(
  • [^)]+?:匹配 ) 以外的任何内容,需要多少次就多少次
  • \)$:匹配行尾的文字)$

或者,如果您想在括号中的单词前后允许其他单词,但括号中没有任何单词,请执行以下操作:

^[^()]*?\([^)]+?\)[^()]*$
试一试:https://regex101.com/r/Ts9JeF/3

解释:

  • ^[^()]*?:在字符串的开头,匹配除括号之外的任何内容零次或多次。
  • \([^)]+?\)非常类似于我们之前的正则表达式
  • [^()]*$:匹配零个或多个 non-parentheses 个字符,直到字符串结束。

non-greedy 限定符使其匹配最短的重复——在这种情况下,最短的成功重复是整个字符串。它不会“不匹配 )”,因为你没有告诉它这样做

你可以想象引擎做这样的事情(使用简化的字符串 '(a) (b)':

  1. 从位置 0 开始
  2. '(' 匹配 (,继续到位置 1
  3. 'a' 匹配 .,继续到位置 2
    • (non-greedy) ')' 匹配 ),继续到位置 3
    • (non-greedy) 字符串结尾不匹配 $ => 回溯到位置 2
  4. ')' 匹配 . 继续到位置 3
    • (non-greedy) ' ' 不匹配 )
  5. ' ' 匹配 . 继续到位置 4
    • (non-greedy) '(' 不匹配 )
  6. '(' 匹配 . 继续到位置 5
    • (non-greedy) 'b' 不匹配 )
  7. 'b' 匹配 . 继续到位置 6
    • (non-greedy) ')' 匹配 )
    • (non-greedy) $ 匹配字符串结尾 => DONE!

试试这个正则表达式的大小:

r'\([^)]+\)$'

这里匹配了一个 left-paren,后跟一个非零数量的 non-right 括号,然后是一个右括号和字符串的结尾