2017-02-11 34 views
0

這裏是我的模式(Live example):如何才能停止匹配,直到第一個特定字符?

(?:"|")id(?:"|"):(?:"|")(.{0,200}?)(?:"|").{0,200}?(?:"|")urn:li:fs_miniCompany:65514(?:"|") 

正如你所看到的,它匹配下面的字符串作爲第一個捕獲組:

/p/3/005/07a/356/1399435.png","$type":"com.linkedin.voyager.common.MediaProcessorImage","$id": 

但這種預期的結果:

/p/3/005/07a/356/1399435.png 

我該怎麼做?


注:我可以使用[^&]+停止匹配,但在這種情況下,它會拋出Catastrophic Backtracking錯誤。

+0

注意到[this](https://regex101.com/r/wqmwDp/5)是我的真實數據。 – Alex

+1

你想要提取的是在結構化數據中,使用結構。 1)解析html以使用'DOMDocument'提取'code'標籤的內容。 2)用'''替換'"e;'3)解碼json並按照它的結構找到你想要的結果 –

+0

@CasimiretHippolyte我看,謝謝 – Alex

回答

0

當您擁有結構化數據時,不要使用字符串方法。實際上,您正在搜索html <code>標記內的JSON字符串內的內容。 使用XPath提取包含子字符串"urn:li:fs_miniCompany:65514"<code>標記文本是一件容易的任務,它將大大減少搜索區域。

然後,所有你需要做的是讓變化不大,以獲得一個JSON字符串(修剪不想要的字符,並用雙引號替換&quote;實體)

$dom = new DOMDocument; 
libxml_use_internal_errors(true); 
$dom->loadHTMLFile('yourfile.html'); // or $dom->loadHTML($yourstring); 

$xp = new DOMXPath($dom); 

$codeContent = $xp->evaluate('string(//code[contains(., "urn:li:fs_miniCompany:65514")])'); 

$json = str_replace('&quote;', '"', trim($codeContent, "\r\n \t\\n")); 
$arr = json_decode($json, true); 

print_r(array_column($arr['included'], 'id')); 

你只需要找到如何根據json結構選擇你想要的那個(使用print_r($arr)來可視化它)


你的模式一般考慮:

  • 避免與交替啓動模式(我看不出有任何理由寫(?:&quote;|")因爲每個報價似乎是由它的HTML實體被替換。&quote;應該就夠了。)如果沒有其他的方法:
    • 嘗試使用研究修改:/pattern/S
    • 嘗試使用的第一個字符識別技術建立你的模式是這樣的:/(?=[&"])(?:&quote;|").../或者這樣說:/[&"](?:(?<=&)quote;|(?<=")).../
    • 最壞的情況下嘗試兩種模式(開始一個字符串的模式提供了很大的改進,因爲在正則表達式引擎開始其正常步行之前,快速算法找到模式可能成功的所有位置)
  • a.*b.*c(如a.*?b.*?ca.{1,n}b.{1,n}ca.{1,n}?b.{1,n}?c是一種公知的災難性回溯的來源。這種模式允許在主題字符串中爲單個位置提供太多組合,並且由於每個組合都經過測試,所以在失敗之前需要很多步驟和時間。
  • 嘗試寫出儘可能快失敗的模式。
1

您可以使用負向預測來匹配除字符序列以外的所有內容。我還建議不要使用{0,200},因爲它似乎很隨機。這種模式匹配第一個PNG路徑。如果你想擁有的最後一個,我會使用,而不是期運用{0,200}一個更具體的選擇:

(?:&quot;|")id(?:&quot;|"):(?:&quot;|")(.*?)(?:&quot;|").*?(?!&quot;).*?(?:&quot;|")urn:li:fs_miniCompany:65514(?:&quot;|") 
+0

謝謝.. upvote – Alex

相關問題