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\-_]+)(?![^<]*>)
^^^^^^^^^^
注意我还转义了 .
符号以匹配文字点,并使用 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\-_]+)
假设我在数据库中有 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\-_]+)(?![^<]*>)
^^^^^^^^^^
注意我还转义了 .
符号以匹配文字点,并使用 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\-_]+)