PHP Youtube URL 的正则表达式否定

PHP Regex Negation For Youtube URLs

假设我在数据库中有 HTML,如下所示:

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 正则表达式来获取第二个和第三个 URL,但忽略第一个。

我目前的正则表达式方程是:

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

它工作得很好,但我不知道如何使它成为 exclude/negate 第一种 URL,以 href="

开头的类型

请帮忙,谢谢!

您只需要添加一个 (?![^<]*>) 否定前瞻,如果匹配后跟 0+ 个字符而不是 < 后跟 >,则匹配失败:

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

regex demo

注意我还转义了 . 符号以匹配文字点,并使用 non-capturing 组和 be 部分。如果您对捕获不感兴趣,可以将 ([a-zA-Z0-9\-_]+) 替换为 [a-zA-Z0-9_-]+,也可以将 [a-zA-Z\/\/:\.]* 部分替换为更精确的模式,例如 https?:\/\/[a-zA-Z.]*.

您可以使用 "negative lookbehind" 正则表达式功能来完成您想要的。我通过添加 ((?<!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

示例解决方案:

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

Visualization with an explanation