什么匹配这个正则表达式:qr /(?!)/;

nov*_*cik 13 regex perl

在一个源代码中,我发现了这个正则表达式:

qr/(?!)/;
Run Code Online (Sandbox Code Playgroud)

我根本无法弄清楚这匹配的是什么.

老实说,绝对不明白什么意味着A零宽度负前瞻断言. - 我在perlre中找到了什么.:(

有人可以用人类语言解释吗?:)

ike*_*ami 25

空正则表达式模式匹配零长度字符串,也就是说它总是匹配.这是一个明显的进展:

'bbbbb' =~ /^(?:aaa|bbb)/   # Matches (Matches 3 "b"s, from pos 0 to 3)
'bbbbb' =~ /^(?:aaa|bb)/    # Matches (Matches 2 "b"s, from pos 0 to 2)
'bbbbb' =~ /^(?:aaa|b)/     # Matches (Matches 1 "b",  from pos 0 to 1)
'bbbbb' =~ /^(?:aaa|)/      # Matches (Matches 0 "b"s, from pos 0 to 0)
Run Code Online (Sandbox Code Playgroud)

这意味着(?=)("这个位置后跟一个零长度的字符串吗?")总是匹配和(?!)("这个位置后面没跟一个零长度的字符串?")从不匹配.事实上,自从后者在5.10中的引入以来,(?!)已经过优化(*FAIL).

(?!)(*FAIL)当模式具有副作用时,aka 也可用于强制回溯.

'abcd' =~ /(.+?)(?{ print "$1\n" })(?!)/;
Run Code Online (Sandbox Code Playgroud)

输出:

a
ab
abc
abcd
b
bc
bcd
c
cd
d
Run Code Online (Sandbox Code Playgroud)

示例说明:

(?!)不匹配,所以正则表达式引擎一直试图通过.+?匹配越来越多的字符来找到匹配.当失败时,正则表达式引擎会尝试在稍后的起始位置进行匹配.

这被称为"回溯".这是正则表达式引擎可以匹配的方式'aaaab' =~ /a*ab/.第一次通过,a*匹配所有4 a秒,所以ab不匹配,所以引擎回溯.第二次通过,a*只匹配as 中的3个,允许ab并因此匹配整个模式.

我最初给出的示例的分步流程如下:

  1. 在pos 0开始匹配.
  2. (.+?)匹配a在pos 0
  3. (?{ print "$1\n" })打印a并匹配零字符
  4. (?!)不匹配.⇒回溯!
  5. (.+?)匹配ab在pos 0
  6. (?{ print "$1\n" })打印ab并匹配零字符
  7. (?!)不匹配.⇒回溯!
  8. (.+?)匹配abc在pos 0
  9. (?{ print "$1\n" })打印abc并匹配零字符
  10. (?!)不匹配.⇒回溯!
  11. (.+?)匹配abcd在pos 0
  12. (?{ print "$1\n" })打印abcd并匹配零字符
  13. (?!)不匹配.⇒回溯!
  14. (.+?)在这里无法匹敌.⇒回溯!
  15. 在pos 1开始匹配.
  16. (.+?)在比赛b1 比赛
  17. (?{ print "$1\n" })打印b并匹配零字符
  18. (?!)不匹配.⇒回溯!
  19. ...
  20. (.+?)比赛d在pos 3
  21. (?{ print "$1\n" })打印d并匹配零字符
  22. (?!)不匹配.⇒回溯!
  23. (.+?)在这里无法匹敌.⇒回溯!
  24. 在pos 4开始匹配.
  25. (.+?)不匹配.⇒回溯!
  26. 模式不匹配.


fge*_*fge 14

这是合法的,但根本不匹配.

(?!...)构造是一个负面的先行断言.详细地说,它意味着:"匹配后面的正则表达式(...)与输入字符串匹配的位置".

但在这种情况下,"后面的正则表达式"是空的正则表达式,它匹配所有东西.

因此,这个正则表达式实质上是说"匹配一个位置,其中后面的内容无法与空正则表达式相匹配"......并且无论输入字符串如何,都不会有这样的位置.这是一个总是失败的正则表达式构造!