2013-04-30 76 views
1

我想要捕獲最多四組<p></p>之間的文本。我能做到這一點使用下面的正則表達式: <h5>Trivia<\/h5><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p>正則表達式可選組

的文本匹配:

<h5>Trivia</h5><p>Was discovered by a freelance photographer while sunbathing on Bournemouth Beach in August 2003.</p><p>Supports Southampton FC.</p><p>She has 11 GCSEs and 2 'A' Levels.</p><p>Listens to soul, R&amp;B, <a href="/name/nm0005567/">Stevie Wonder</a>, <a href="/name/nm0291349/">Aretha Franklin</a>, <a href="/name/nm0713378/">Usher Raymond</a>, <a href="/name/nm0001391/">Michael Jackson</a> and <a href="/name/nm0584117/">George Michael</a>.</p>

它輸出的文本四行。如果還有更多的瑣事項目或<p>事件,它也可以按預期工作。

但是如果有少於4個瑣事項或<p>組,它將不輸出任何內容,因爲它找不到第四組。我如何使該組成爲可選項?

我試過:<h5>Trivia<\/h5><p>(.*?)<\/p>(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?和那根據http://gskinner.com/RegExr/工作,但它不工作,如果我把它放進PHP代碼。它只檢測一個組並將所有內容放入其中。

+0

您使用哪個分隔符?因爲你沒有在最後一個正則表達式中轉義'/'es。沒有明顯的原因,爲什麼選擇性方法不適用。 - 另外,儘管我並沒有試圖譏諷陳舊的模因,但在HTML/DOM遍歷方面,這可能比正則表達式更簡單(儘管對於這種情況足夠了,並且您的輸入是中等連貫的)。但爲簡單起見,請參閱phpQuery或QueryPath,如果空閒時間過長,請參閱原始DOM方法。 – mario 2013-04-30 22:57:58

+0

我錯誤地排除了最後一個正則表達式中的/(對實際嘗試的正則表達式進行採樣)。爲了清晰起見編輯了這些內容。感謝您的建議。 – zataived 2013-05-01 00:36:36

回答

1

魔術詞是'轉義'或'分隔符',請繼續閱讀。

第一個正則表達式:
<h5>Trivia<\/h5><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p><p>(.*)<\/p>
工作,因爲你逃過標籤/字符,例如</h5><\/h5>

但在你的第二個正則表達式(正確地封閉在可選的非捕獲組的每個段落,取1至5段):
<h5>Trivia</h5><p>(.*?)</p>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?
你忘了逃生者/字符。
那麼它應該是:
$pattern = '/<h5>Trivia<\/h5><p>(.*?)<\/p>(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?(?:<p>(.*?)<\/p>)?/';

以上是假設你把(出傳統習慣)兩大/「分隔符」字符之間的正則表達式。

要深入一點兔子洞,應該注意,在php中,正則表達式的第一個和最後一個字符通常是「delimiter」,所以可以在末尾添加修飾符(如不區分大小寫等等)。

因此,您也可以使用~字符(或#等)作爲分隔符而不是轉義您的正則表達式。
因此,你也可以使用相同相同的(第二),您發佈的正則表達式和封裝例如像這樣:
$pattern = '~<h5>Trivia</h5><p>(.*?)</p>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?~';

這裏是工作的是(基於Web)example,使用#作爲分隔符(只因爲我們可以)。

+0

你最後一個小提琴把#作爲分隔符與$ pattern組合而不是//(我最初在我的preg_match中使用過)組合使用了這個技巧。感謝您的額外信息和答案!其他組合或者報告了一個未定義的偏移量,或者連接[0]中的所有組。 – zataived 2013-05-01 00:30:19

1

可以使用問號,使每個<p>...</p>可選:

$pattern = '~<h5>Trivia</h5>(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?(?:<p>(.*?)</p>)?~'; 

使用DOM過一個不錯的選擇。

+0

你說:'*您可以使用問號使每個

...

可選*'。提問者已經在他的第二個正則表達式中做了這些(正確地將段落包含在一個可選的非捕獲組中)(區別在於:他的正則表達式搜索非可選的第一段,然後是4個可選段落)。所以,雖然你的代碼工作,但它不解釋*爲什麼*。然而,+1暗示更好的解決方案,而不是regexing標籤湯。 – GitaarLAB 2013-05-01 00:22:41