2010-02-05 115 views
8

的比賽我有一個字符串,它可能是這個樣子:PHP正則表達式 - 重複一組

$r = 'Filed under: <a>Group1</a>, <a>Group2</a>'; 

這裏是正則表達式我使用至今:

preg_match_all("/Filed under: (?:<a.*?>([\w|\d|\s]+?)<\/a>)+?/", $r, $matches); 

我想在()內部的正則表達式繼續進行匹配,如最後指定的+?。但它不會這樣做。 ::感嘆::

任何想法。我知道必須有一種方法可以在一個正則表達式中完成此操作,而不是將其分解。

回答

5

嘗試:

<?php 

$r = 'Filed under: <a>Group1</a>, <a>Group2</a>, <a>Group3</a>, <a>Group4</a>'; 

if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $r, $matches)) { 
    var_dump($matches[1]); 
} 

?> 

輸出:

array(4) { 
    [0]=> 
    string(6) "Group1" 
    [1]=> 
    string(6) "Group2" 
    [2]=> 
    string(6) "Group3" 
    [3]=> 
    string(6) "Group4" 
} 

編輯:

既然你要在搜索中包括「下一篇」唯一標識匹配的字符串,你可以試試這個,我不知道它是否可以使用單個調用的preg_match

// Since you want to match everything after 'Filed under' 
if(preg_match("/Filed under:(.*)$/", $r, $matches)) { 
    if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $matches[1], $matches)) { 
     var_dump($matches[1]); 
    } 
} 
+0

謝謝,但我真的需要使用「Filed under:」標誌。雖然我的示例文本是基本的,但我解析的實際文件卻非常複雜,而歸檔於:是我必須使用的唯一唯一標識符。幸運的是,它在文件末尾,所以我可以一直匹配到最後。 – 2010-02-05 04:22:08

+0

足夠接近。 :) 謝謝。 – 2010-02-05 05:21:03

1

我想要正則表達式在()中繼續進行匹配,並用+指定。最後。

+?是惰性限定符 - 它將匹配倍可能。換句話說,就是一次。

如果你想匹配多次,你想要一個貪婪的量詞 - +

另請注意,您的正則表達式不太適用 - 只要遇到標籤之間的逗號,匹配就會失敗,因爲您沒有考慮到它。這可能需要糾正。

+0

對,我試過了+量詞。這也失敗了。而且我也考慮過,[恐懼],恐怕我不知道該如何設置,因爲第二或第三場比賽可能沒有逗號。我做了這個嘗試: [code] preg_match_all(「/提起下:(?:([\ w | \ d | \ s] +?)<\/a>。*?)+ /」,$ r ,$匹配); [/ code] – 2010-02-05 04:15:26

+0

嗯,評論看起來不太漂亮。 – 2010-02-05 04:15:46

+0

@Senica:您可以像在問題和答案中一樣使用反引號來格式化代碼,但如果代碼很長或很複雜,您應該編輯您的問題並將其放在那裏。你上面包含的代碼有點評論。 – 2010-02-05 09:25:09

2
$r = 'Filed under: <a>Group1</a>, <a>Group2</a>' 
$s = explode("</a>",$r); 
foreach ($s as $k){ 
    if ($k){ 
     $k=explode("<a>",$k); 
     print "$k[1]\n"; 
    } 
} 

輸出

$ php test.php 
Group1 
Group2 
+1

有時RegExes真的是做某事的最佳方式...... – SoapBox 2010-02-05 04:15:55

+1

最好與否,取決於個人。如果不需要複雜的正則表達式,那麼對我來說是最好的,無論對於我自己還是對維護它的人來說都是如此。 – ghostdog74 2010-02-05 04:20:26

+0

正如我在上面的評論中所解釋的那樣,我不能使用爆炸....例如,有些情況下沒有逗號並且只有一個組。二,雖然我的例子很簡單,但這是一個複雜的文件。 標籤也不那麼簡單。三,我需要提交下:屬性作爲使用爆炸肯定會返回不需要的值。 – 2010-02-05 04:44:25

8
完成

只是爲了好玩這裏有一個正則表達式將與一個preg_match_all工作:

'%(?:Filed under:\s*+|\G</a>)[^<>]*+<a[^<>]*+>\K[^<>]*%` 

或者,在一個更可讀的格式:

'%(?: 
     Filed under: # your sentinel string 
    |     
     \G    # NEXT MATCH POSITION 
     </a>   # an end tag 
) 
    [^<>]*+   # some non-tag stuff  
    <a[^<>]*+>  # an opening tag 
    \K    # RESET MATCH START 
    [^<>]+   # the tag's contents 
%x' 

\G與下一場比賽嘗試開始的位置相匹配,這通常是上一次成功比賽結束的位置(但如果前一場比賽是零長度,則會前進一場)。這意味着正則表達式將不匹配從</a>開始的子字符串,直到後的與至少一次從Filed under:開始匹配。

在哨兵字符串或結束標記匹配後,[^<>]*+<a[^<>]*+>消耗了一切,直至包括下一個開始標記。然後\K欺騙起始位置,以便匹配(如果有的話)似乎在<a>標籤後面開始(這看起來像是一個積極的後視,但更靈活)。最後,[^<>]+匹配標籤的內容並將匹配位置帶到結束標籤,以便\G可匹配。

但是,正如我所說的,這只是爲了好玩。如果你不需要在一個正則表達式中完成這項工作,你最好使用一個像@codaddict一樣的多步驟方法;它更具可讀性,更靈活,更易於維護。

\K reference
\G reference

編輯:雖然我給的引用是爲Perl的文檔,這些功能是由PHP支持,太 - 或者,更準確地說,是由PCRE庫。我認爲Perl文檔好一點,但是您也可以在PCRE manual中閱讀這些內容。

+0

我不知道'\ K'。有趣!關於'\ G'的一個小記錄 - 您指的是「上一個匹配」,這是可以的,並且指向「下一個匹配」,這有點令人困惑(特別是當您鏈接的Perl示例完全具有誤導性時 - 它*設置*代碼中的下一個位置 - **,這與默認行爲**)非常不同。簡單地說 - '\ G'指的是當前匹配嘗試開始的位置。它也不是準確的''將總是匹配'Filed under:'之後 - 它也可以匹配字符串的開頭,for例如', Group2':http://ideone.com/aTjrm。 – Kobi 2011-08-21 04:22:47

+0

(順便說一句,我來自這裏:http://stackoverflow.com/questions/5982451/regex-capturing-a-repeated-group/7135730#7135730) – Kobi 2011-08-21 04:27:10

+0

嗯,實際上,我對'\ G'的定義是不好。 – Kobi 2011-08-21 04:41:32