Perl регулярное выражение становится жадным при использовании (.*?) С якорями
У меня есть 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]
2 ответа
Вы действительно хотите соответствовать >
персонажи? Бьюсь об заклад, вы не... Так что не используйте.*
и это решит вашу проблему жадности. использование [^>]*
вместо. Он гарантированно остановится, как только он достигнет первого >
(даже без привязки к ?
) так как >
не совпадает
$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 - рассматривать строку как одну строку. То есть изменить "." соответствовать любому символу, даже символу новой строки, который обычно не соответствует. Используются вместе, как / мс, они позволяют "." соответствует любому символу, в то же время позволяя сопоставлять "^" и "$", соответственно, сразу после и непосредственно перед символами новой строки в строке.
x - Увеличьте разборчивость вашего шаблона, разрешая пробелы и комментарии.
Тогда ваш код будет выглядеть намного более читабельным, и вы увидите, что он содержит много неиспользуемых групп захвата, а также мертвый код и небольшие ошибки, например, использование unescaped `.` в группе захвата URL.
После всех модификаций и, как говорит Дейв Шерохман, использование `[^>]*` вместо `.*?` Ваш код будет выглядеть намного лучше, не так ли?. Проверь это:
$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;
И это работает отлично!