2013-06-01 179 views
13

在一個源代碼,我發現這個正則表達式:匹配這個正則表達式:qr /(?!)/;

qr/(?!)/; 

我根本想不通這是什麼比賽。

老實說,絕對不明白是什麼意思一個零寬度的負向預測斷言。 - 我在perlre中發現的。 :(

有人能解釋它在人類的語言嗎?:)

回答

14

這是合法的,但完全沒有匹配。

(?!...)構造是負向超前斷言。具體來說,它的意思是:「匹配後面的正則表達式(...)應與而不是匹配輸入字符串的位置」。

但在這種情況下,「後面的正則表達式」是空的正則表達式,它匹配所有內容。

所以,這個正則表達式本質上是說「匹配後面的位置不能被空的正則表達式匹配」......並且不管輸入字符串如何,都不能有這樣的位置。這是一個總是失敗的正則表達式構造!

+0

不想說謊 - 所以不能說:啊,現在完全明白了。但是,你的解釋給了我一些關於黑暗的光。謝謝。 :)接受。 – novacik

+0

我可以提供更多關於需求的細節;)特別是,正則表達式中的_anchor_意味着什麼。如果你願意,我可以對錨的內部工作給出一個完整的,更詳細的解釋;) – fge

1

(?=),空積極前瞻,會始終保持一致。設置最後一次成功匹配的價值是一種駭人的方式。 (?!)是它的倒數,並且永遠不會匹配。

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) 

這意味着(?=)(「難道這個位置後跟一個零長度字符串」)始終匹配和(?!)(「是這個位置後面沒有零長度字符串?」 )從來沒有匹配。實際上,自從後者在5.10中引入後,(?!)被優化爲(*FAIL)

(?!) aka (*FAIL)在模式有副作用時強制回溯是有用的。

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

輸出:

a 
ab 
abc 
abcd 
b 
bc 
bcd 
c 
cd 
d 

例子說明:

(?!)不匹配,因此正則表達式引擎不停地嘗試找到一個匹配具有.+?比賽越來越多字符。如果失敗,則正則表達式引擎會嘗試在稍後的起始位置進行匹配。

這被稱爲「回溯」。正則表達式引擎可以匹配'aaaab' =~ /a*ab/。第一次通過,a*匹配所有4 a s,所以ab不匹配,所以引擎回溯。第二次通過,a*只匹配a s中的3個,允許ab並因此整個模式匹配。

的步驟通過用於我原先給的例子步驟流程如下:

  1. 開始在pos 0
  2. (.+?)比賽a在pos 0
  3. (?{ print "$1\n" })打印a和匹配零個字符
  4. 匹配
  5. (?!)不符。 ⇒回溯!
  6. (.+?)比賽ab在pos 0
  7. (?{ print "$1\n" })打印ab和匹配零個字符
  8. (?!)不匹配。 ⇒回溯!
  9. (.+?)比賽abc在pos 0
  10. (?{ print "$1\n" })打印abc和匹配零個字符
  11. (?!)不匹配。 ⇒回溯!
  12. (.+?)比賽abcd在pos 0
  13. (?{ print "$1\n" })打印abcd和匹配零個字符
  14. (?!)不匹配。 ⇒回溯!
  15. (.+?)無法匹配其他任何東西。 ⇒回溯!
  16. 開始在pos 1.
  17. (.+?)比賽b匹配在pos 1個
  18. (?{ print "$1\n" })打印b和匹配零個字符
  19. (?!)不匹配。 ⇒回溯!
  20. ...
  21. (.+?)比賽d在pos 3
  22. (?{ print "$1\n" })打印d和匹配零個字符
  23. (?!)不匹配。 ⇒回溯!
  24. (.+?)無法匹配其他任何東西。 ⇒回溯!
  25. 開始在位置4處匹配。
  26. (.+?)不符合。 ⇒回溯!
  27. 模式不匹配。
+0

我需要學得更多才能夠理解這個例子。我明白'(。+?)'=匹配儘可能最短的字符串,並將其添加到捕獲組,理解'push ...',但不知道爲什麼它重複 - 爲什麼會給出上述結果。我只是一名初學者 - 但謝謝你。 ;) – novacik

+0

'(?!)'不匹配,所以正則表達式引擎通過讓'。+?'匹配更多字符來不斷嘗試找到匹配項。如果失敗,則正則表達式引擎會嘗試在稍後的起始位置進行匹配。這被稱爲「回溯」。正則表達式引擎可以匹配''aaaab'=〜/ a * ab /'。第一次,'a *'匹配所有5個''',所以'ab'不匹配,所以它回溯。第二次,'a *'只匹配4個''',允許'ab'匹配。 – ikegami

+0

...我以爲我知道正則表達式 – kizzx2