PHP preg_replace - 不匹配锚链接

PHP preg_replace - do not match anchor links

我的 Wordpress 主题中有一个自定义功能,用于查找 YouTube 网址并自动将它们转换为嵌入式 iframe。这很好用,但有一个小问题。目前,该功能还取代了链接到文本的 YouTube 链接。因此,如果我有一个指向 YouTube 的锚标记,它会将 iframe 代码扔到锚中并导致 HTML 问题。

因此,如果我有一个 Wordpress post 并且我在 post 中有以下内容,我希望将其转换为 iframe:

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

但是如果我有链接到 YouTube 的文本,我不希望它被转换:

<a href="https://www.youtube.com/watch?v=HDDLTwS4zgs">Check out Linus' latest video</a>

这是我的 PHP 函数:

function convertYoutube($string) {
    return preg_replace(
        "/\s*[a-zA-Z\/\/:\.]*youtu(be.com\/watch\?v=|.be\/)([a-zA-Z0-9\-_]+)([a-zA-Z0-9\/\*\-\_\?\&\;\%\=\.]*)/i",
        "<div class=\"embed-responsive embed-responsive-16by9 scroll-in\"><iframe width=\"560\" height=\"315\" src=\"//www.youtube.com/embed/\" frameborder=\"0\" allowfullscreen></iframe></div>",
        $string
    );
}

add_filter('the_content', 'convertYoutube');

可以通过添加 <a\b[^>]*>[^<]*</a>(*SKIP)(*FAIL)| 替代方案来修复模式:

'~<a\b[^>]*>[^<]*</a>(*SKIP)(*FAIL)|\s*[a-zA-Z/:.]*youtu(be\.com/watch\?v=|\.be/)([\w-]+)([\w/*?&;%=.-]*)~'

参见regex demo

另请注意,如果您使用不同的正则表达式分隔符,则 / 不需要转义。字符 class、[...] 之外的 . 必须转义以匹配文字点。如果不使用 u 修饰符,\w 等于 [A-Za-z0-9_]。字符 class、[...] 内的 - 不必在 class 的 start/end 处(以及在范围或 shorthand 字符 class).

更新模式详细信息

<a\b - 匹配整个字符串 <a - [^>]* - > 以外的 0+ 个字符 - > - > 符号 - [^<]* - < 以外的 0+ 个字符 - </a> - 文字子串 - (*SKIP)(*FAIL) - PCRE 动词跳过匹配并在上一个省略的匹配结束时继续搜索新匹配。