2017-02-03 28 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.]*