2017-02-03 25 views
4

比方說,我有HTML中,看起來像這樣一個數據庫:PHP正則表達式否定對於YouTube網址

Hello world! 

<a href="https://www.youtube.com/watch?v=m7t75u72vd">ABC</a> 

Blah blah blah... 

https://www.youtube.com/watch?v=df82vnx07s 

Blah blah blah... 
<p>https://www.youtube.com/watch?v=nvs70fh17f3fg</p> 

現在我想用PHP正則表達式來獲取第二和第三的網址,卻忽略了第一。

正則表達式方程我至今是:

\s*[a-zA-Z\/\/:\.]*youtu(be.com\/watch\?v=|.be\/)([a-zA-Z0-9\-_]+) 

它工作得很好,但我不知道如何使它排除/否定第一種類型的URL,其中一個開頭:HREF =」

請幫幫忙,謝謝

+1

提取與DOM文檔/ DOMXPath文本節點第一(避免鏈接),然後搜索他們每個人的創造(最終)新的鏈接節點。 –

+0

我想使用preg_match在PHP中執行所有操作,因爲HTML位於數據庫中,而且我的代碼已經爲其構建。 – liquidgraph

+1

不要使用正則表達式來解析HTML。 http://php.net/DomDocument – miken32

回答

1

您可以使用「負面後顧」正則表達式功能來完成您所追求的內容。我通過添加((?<!href=[\'"])http)來實現一個修改了正則表達式的一開始。希望能幫助到你!

$regex = '/((?<!href=[\'"])http)[a-zA-Z\/\/:\.]*youtu(be.com\/watch\?v=|.be\/)([a-zA-Z0-9\-_]+)/'; 
$useCases = [ 
    1 => '<a href="https://www.youtube.com/watch?v=m7t75u72vd">ABC</a>', 
    2 => "<a href='https://www.youtube.com/watch?v=m7t75u72vd'>ABC</a>", 
    3 => 'https://www.youtube.com/watch?v=df82vnx07s', 
    4 => '<p>https://www.youtube.com/watch?v=nvs70fh17f3fg</p>' 
]; 
foreach ($useCases as $index => $useCase) { 
    $matches = []; 
    preg_match($regex, $useCase, $matches); 
    if ($matches) { 
     echo 'The regex was matched in usecase #' . $index . PHP_EOL; 
    } 
} 
// Echoes: 
// The regex was matched in usecase #3 
// The regex was matched in usecase #4 
0

所有你需要的是增加一個(?![^<]*>)負先行如果比賽之後與比<其他0+字符隨後與>將失敗的比賽:

[a-zA-Z\/:.]*youtu(?:be\.com\/watch\?v=|\.be\/)([a-zA-Z0-9\-_]+)(?![^<]*>) 
                    ^^^^^^^^^^ 

參見regex demo

注我也逃脫.符號匹配文字的點,和使用非捕獲組be一部分。如果您對捕捉不感興趣,您可以將([a-zA-Z0-9\-_]+)替換爲[a-zA-Z0-9_-]+,也可以用更精確的模式替換[a-zA-Z\/\/:\.]*部件,如https?:\/\/[a-zA-Z.]*