2009-08-13 640 views
3

之間的字符串我試圖匹配包含在%s中的子字符串,但preg_match_all似乎在同一行中包含多個字符串。正則表達式匹配%

代碼如下所示:

preg_match_all("/%.*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
print_r($matches); 

將會產生以下輸出。

Array 
(
    [0] => Array 
     (
      [0] => %hey%_thereyou're_a%rockstar% 
      [1] => %there% 
     ) 

) 

但是我想它產生以下數組來代替:

[0] => %hey% 
[1] => %rockstar% 
[2] => %there% 

我缺少什麼?

回答

12

在你的正則表達式爲「[^%]‘替換「.」:

preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

正在發生的事情是,’.」是「貪婪」匹配一樣,因爲它可能會,內容包括上調到線上的最後%。將其替換爲否定字符類「[^%]」意味着它將代替之間的任何匹配項,除了以外的百分比,這將使它僅匹配所需的位。

另一種選擇是放置一個「?」後點,告訴它「不貪」:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

在上面的例子,兩個選項都可以工作,但是有次當你可能在尋找比單個字符更大的東西時,所以否定字符類將無濟於事,因此解決方法是不要貪婪地匹配。

+0

它的工作原理。謝謝! – Spoike 2009-08-13 08:08:15

4

你做一個貪婪的比賽 - 用?,使之ungreedy:

/%.*?%/ 

如果換行可以在比賽中出現,添加S(DOTALL)修改器:

/%.*?%/s 
1

原因是明星是貪婪的。也就是說,星星會使正則表達式引擎儘可能頻繁地重複前一個標記。你應該試試 。*?代替。

1

你可以試試/%[^%]+%/ - 這意味着你只想匹配不是百分號的字符。

你也可以使圖案不明確,例如,所以它會盡可能少的捕獲(我認爲)。

+0

更準確地說,'/ U'反轉了正則表達式中所有量詞的貪婪,所以'/ %.+%/U'與'/%.+?%/'相同,'/%.+?%/U'與'/%.+%/'相同。 http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php – 2009-08-19 13:27:12

2

添加?之後*:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
1

|%(\ w +)%|這將工作正是你想要的。