2011-03-18 75 views
16

當涉及匹配涉及美元符號的子模式時,我遇到了一些問題。例如,考慮下列文本塊:當模式涉及美元符號時,正則表達式失敗

Regular Price: $20.50  Final Price: $15.20 
Regular Price: $18.99  Final Price: $2.25 
Regular Price: $11.22  Final Price: $33.44 
Regular Price: $55.66  Final Price: $77.88 

我試圖匹配正/最終價格設置與下面的正則表達式,但它根本沒有工作(不匹配的話):
preg_match_all("/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U", $data, $matches);

我躲過了美元符號,所以給了什麼?

+1

嘗試用美元符號\\\轉義。推斷問題美元符號與PHP使用$做一些工作的事實之間的關係可能沒有問題。 (我也使用$做工作,它只是看起來合乎邏輯)。 – 2011-03-18 21:31:06

+3

你試過單引號而不逃避$? – palindrom 2011-03-18 21:31:07

回答

32

在雙引號字符串中,反斜槓被視爲$的轉義字符。反斜槓由preg_match_all功能看到它甚至在PHP解析器刪除:

$r = "/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U"; 
var_dump($r); 

輸出(ideone):

 
"/Regular Price: $(\d+\.\d{2}).*Final Price: $(\d+\.\d{2})/U" 
       ^      ^
       the backslashes are no longer there 

爲了解決這個問題用一個單引號字符,而不是一個雙引號的字符串:

preg_match_all('/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U', 
       $data, 
       $matches); 

看到它聯機工作:ideone

+0

...或者你也可以在'\ $'之前加一個\,結果相同。它不太漂亮,但它工作得很好。 – 2011-05-18 14:18:53

+0

我有同樣的問題,現在感覺很蠢,謝謝! – jreed121 2011-10-20 16:00:33

+0

您的解決方案也適用於我使用Perl – Filype 2012-05-27 11:16:04

6

我知道這個問題有點老,但我在找到答案時發現了這個問題。我一看,原來是在搜索引擎排名的頂部,所以我想這將是很好解釋的簡單替代,爲什麼出現這種情況有雙引號中的字符串(")

正則表達式我用的是含有大量的單引用其中的字符('),所以我不太願意與他們包裝表達,因爲我不想逃避所有這些。

我的解決方案是「雙重逃避」美元符號。在你的榜樣,它應該類似於東西

"/Regular Price: \\\$(\d+\.\d{2}).*Final Price: \\\$(\d+\.\d{2})/U"; 

需要注意的是美元符號包含現在\\\ 3條斜線。

基本上,我們有兩個「層次」的解釋,即PHP和正則表達式的解釋。發生的事情是,使用一個斜槓,PHP將其解釋爲文字字符而不是變量修飾符,因此它會吃掉斜線,按照Mark的答案解釋字符串,然後將其發送給正則表達式,後者將解釋爲後退。

通過「雙重轉義」美元符號,PHP將\\\$分別解釋爲\\\$。我們從第一組字符中跳出了\,並且從第二組中跳出$,導致PHP解釋後只有\$。這將發送文本字符串

"/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U"; 

於正則表達式,這將解釋\$作爲字符文字$,這將匹配$,而不是背後充當一看,因爲它是逃脫。在這裏實現雙層解釋非常重要,因爲PHP和正則表達式都有自己的解釋規則,並且可能最多需要4個斜線才能正確轉義字符。

單引號字符沒有這個問題,因爲在一個字符串中使用一個變量$foo,我們會寫

'Hello '. $foo .'!'; 

,而不是

​​

喜歡,我們可以在雙字符串。與雙引號字符串不同,單引號字符串不能將字符串內部的變量解釋爲變量(除非像上面的例子中那樣添加它們),而是將它們解釋爲純文本。因爲我們不必再逃避變量,我們可以逃脫只是

'/Regular Price: \$(\d+\.\d{2}).*Final Price: \$(\d+\.\d{2})/U' 

將發送\$到正則表達式,同樣與\\\$在雙引號字符串。

這是所有關於您使用哪種風格或哪種模式更容易的個人偏好的問題。

TL; DR:對單引號字符串使用\$,如'/Hello \$bob/is'\\\$,用於雙引號字符串,如"/Hello \\\$bob/is"

相關問題