0

我有一个 perl 正则表达式可以将 youtube 视频链接添加到视频标签。YouTube 视频链接有时可以在锚点内,有时也可以没有锚点。我已经使用 (.*?) 检查了具有任何值的锚点,但它表现得很贪婪。下面是我正在使用的正则表达式。

$text =~ s#(^|\s|\>)(?:<a(.*?)\>)?((http|https)://(?:www.)?(?:youtu.be/|youtube.com(?:/embed/|/v/|/watch\?v=|/watch\?[a-z_=]+&(amp;)?v=))([\w-]{11}))[\?&\w;\=\+\-\.]*(\<\/a\>)?#$1\[video\]$3\[\/video\]#isg;

请帮助使其不贪婪。

输入数据样本:

<a rel="nofollow" href="https://www.facebook.com/photo.php?v=639296402756602" target="_blank">https://www.facebook.com/photo.php?v=639296402756602</a>

<a rel="nofollow" href="https://www.youtube.com/watch?v=9gTw2EDkaDQ" target="_blank">https://www.youtube.com/watch?v=9gTw2EDkaDQ</a>

我期待以下输出:

<a rel="nofollow" href="https://www.facebook.com/photo.php?v=639296402756602" target="_blank">https://www.facebook.com/photo.php?v=639296402756602</a>

[video]https://www.youtube.com/watch?v=9gTw2EDkaDQ[/video]

但它只返回 youtube 链接。它忽略了 facebook 视频链接。

[video]https://www.youtube.com/watch?v=9gTw2EDkaDQ[/video]
4

2 回答 2

1

$text =~ s#(^|\s|\>)(?:<a(.*?)\>)?((http|https)://(?:www.)?(?:youtu.be/|youtube.com(?:/embed/|/v/|/watch\?v=|/watch\?[a-z_=]+&(amp;)?v=))([\w-]{11}))[\?&\w;\=\+\-\.]*(\<\/a\>)?#$1\[video\]$3\[\/video\]#isg;

这个正则表达式是不可读的,没有人愿意阅读它。请记住,正则表达式也是程序,它们也需要代码格式化。

始终对所有正则表达式使用 `smx` 修饰符,这是非常好的做法,例如`始终使用严格和警告`。

m - 将字符串视为多行。也就是说,将“^”和“$”从仅匹配字符串左右两端的行首或行尾更改为匹配字符串中的任何位置。

s - 将字符串视为单行。即改“.”。匹配任何字符,甚至是换行符,通常它不会匹配。一起使用,作为/ms,他们让“。” 匹配任何字符,同时仍然允许 "^" 和 "$" 分别匹配字符串中的换行符之后和之前。

x - 通过允许空格和注释来扩展模式的易读性。

然后您的代码将看起来更具可读性,并且您会看到它包含许多不可用的捕获组、死代码和小错误,例如在 url 捕获组中使用未转义的 `.`。

在所有修改之后,正如 Dave Sherohman 所说,使用 `[^>]*` 而不是 `.*?` 你的代码看起来会更好,不是吗?看一下这个:

$text =~ s{
                (?:<a[^>]*>)?
                (
                    http[s]?://
                    (?:www[.])?
                    youtu[.]?be(?:[.]com)?
                    (?:/embed/|/v/|/watch\?v=|/watch\?[a-z_=]+&(?:amp;)?v=)
                )
                ([\w-]{11})
                [^<]*
                (?:</a>)?
            }
            {
                \[video\]$1$2\[/video\]
            }smxgi;

它工作正常!

于 2013-07-29T07:50:42.333 回答
1

真的要匹配>字符吗?我打赌你不会......所以不要使用.*,这将解决你的贪婪问题。改为使用[^>]*。保证在碰到第一个时立即停止>(即使没有附加 a ?),因为>不匹配。

于 2013-07-29T07:21:32.827 回答