Почему это регулярное выражение работает с одним URL-адресом, а не с другим?

Итак, я использую это регулярное выражение, которое преобразует все сообщения из твиттера во встроенный твит:

'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i'

Но когда я пытаюсь сделать то же самое для Instagram или Facebook, это не срабатывает:

'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?instagram\.com/p/([^&]+)\S*~i'

'~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i'

Регулярное выражение почти полностью такое же, а ссылки на твиттер почти идентичны ссылкам на фейсбуке, например. https://twitter.com/USER/status/idnumberhttps://www.facebook.com/USER/posts/idnumber. Instagram делает почти то же самое, но любит этот https://www.instagram.com/p/id

Причина, по которой я использую ~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)| в начале регулярного выражения, заключается в том, что у меня есть BBCode на моем сайте, и вы можете увидеть мой предыдущий вопрос о регулярном выражении здесь

Обновлено:

Вот полное регулярное выражение и замена:

$search = array (
    '~\[b](.*?)\[/b]~is',
    '~\[i](.*?)\[/i]~is',
    '~\[u](.*?)\[/u]~is',
    '~\[ul](.*?)\[/ul]~is',
    '~\[li](.*?)\[/li]~is',
    '~\[user=(.*?)](.*?)\[/user]~i',
    '~\[url=https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12})].*?\[/url]~i',
    '~\[url]https?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}).*?\[/url]~i',
    '~\[url=((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)](.*?)\[/url]~i',
    '~\[url]((?:ht|f)tps?://[a-z\d.-]+\.[a-z]{2,3}/\S*?)\[/url]~i',
    '~\[img=(.*?)].*?\[/img]~i',
    '~\[quote](.*?)\[/quote]~is',
    '~\[code](.*?)\[/code]~is',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|(?:\bhttps?.*?(?:[/?&](?:e|vi?|ci)(?:[/=]|%3D)|youtu\.be/|embed/|/user/[^/]+#p/(?:[^/]+/)+)([\w-]{10,12}))\S*~i',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?clips\.twitch\.tv/([^&]+)\S*~i',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?imgur\.com/gallery/([^&]+)\S*~i',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?twitter\.com/([^&]+)/status/([^&]+)\S*~i',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://(?:www:)?facebook\.com/([^&]+)/posts/([^&]+)\S*~i',
    '~(?:<a.*?</a>|<img.*?</img>|<iframe.*?</iframe>)(*SKIP)(*FAIL)|\bhttps?://.+?(?=\s|$)~im'
);

$replace = array (
    '<strong>$1</strong>',
    '<em>$1</em>',
    '<u>$1</u>',
    '<ul>$1</ul>',
    '<li>$1</li>',
    '<a href = "../login/profile?u=$1" target = "_blank">$2</a>',
    '<br><iframe width = "600" height = "315" src = "//www.youtube.com/embed/$1" frameborder = "0" allow = "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
    '<br><iframe width = "600" height = "315" src = "//www.youtube.com/embed/$1" frameborder = "0" allow = "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
    '<a href = "$1" target = "_blank" rel = "nofollow">$2</a>',
    '<a href = "$1" target = "_blank" rel = "nofollow">$1</a>',
    '<img src = "$1"></img>',
    '<quote>$1</quote>',
    '<code>$1</code>',
    '<br><iframe width = "600" height = "315" src = "//www.youtube.com/embed/$1" frameborder = "0" allow = "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br>',
    '<br><iframe width = "600" height = "315" src = "//clips.twitch.tv/embed?clip=$1&autoplay=false" frameborder = "0" allowfullscreen></iframe><br>',
    '<blockquote class = "imgur-embed-pub" lang = "en" data-id = "$1"><a href = "//www.imgur.com/$1"></a></blockquote><script async src = "//s.imgur.com/min/embed.js" charset = "utf-8"></script>',
    '<blockquote class = "twitter-tweet" data-lang = "en"><p lang = "en" dir = "ltr"><a href = "//twitter.com/$1/status/$2?ref_src=twsrc%5Etfw"></a></blockquote><script async src = "//platform.twitter.com/widgets.js" charset = "utf-8"></script>',
    '<iframe src = "//www.facebook.com/plugins/post.php?href=//www.facebook.com/$1/posts/$2&width=500" width = "500" height = "705" style = "border:none;overflow:hidden" scrolling = "no" frameborder = "0" allowTransparency = "true" allow = "encrypted-media"></iframe>',
    '<a href = "$0" target = "_blank" rel = "nofollow">$0</a>'
);

Опубликуйте код и содержимое строки, по которой вы вызываете preg_replace().

Barmar 02.11.2018 21:15

@Barmar Я выложил.

TheWelshManc 02.11.2018 23:34

Можете ли вы добавить ввод и ожидаемый результат? Для URL-адреса facebook я получаю <a href = "https://www.facebook.com/USER/posts/idnumber" target = "_blank" rel = "nofollow">https://www.facebook.com/USER/posts/idnumber<‌​/a>. Что должно быть вместо этого?

Barmar 02.11.2018 23:41

Я его выложил, должно быть <iframe src = "//www.facebook.com/plugins/post.php?href=//www.facebook‌​.com/$1/posts/$2&wid‌​th=500" width = "500" height = "705" style = "border:none;overflow:hidden" scrolling = "no" frameborder = "0" allowTransparency = "true" allow = "encrypted-media"></iframe>

TheWelshManc 02.11.2018 23:45

Я не вижу этого нигде в вопросе.

Barmar 02.11.2018 23:47

Внизу внизу прокрутите вниз

TheWelshManc 02.11.2018 23:47

Последнее, что я вижу, это $replace = array(...);

Barmar 02.11.2018 23:48

У вас опечатка в регулярном выражении. (?:www:)? должен быть (?:www\.)?

Barmar 02.11.2018 23:56

Ваше регулярное выражение соответствует www:facebook.com, а не www.facebook.com

Barmar 02.11.2018 23:57

Странно, потому что мое другое регулярное выражение работает по ссылке в твиттере

TheWelshManc 02.11.2018 23:59

Часть www: не является обязательной, поэтому она соответствует twitter.com или www:twitter.com, и аналогично для facebook и instagram. Вы тестировали twitter.com, но не www.twitter.com.

Barmar 03.11.2018 00:02

Я изменил: на. но это не сработало должным образом. Я тогда не понимаю, как работают другие.

TheWelshManc 03.11.2018 00:12

У меня работает, когда я меняю их все. ideone.com/YRBSWD

Barmar 03.11.2018 00:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
13
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не зная, что вы видите несколько примеров URL-адресов, из которых вы пытаетесь извлечь, трудно сказать с абсолютной уверенностью, но, возможно, я могу дать несколько общих советов.

([^&]+) <- Это будет захват одного или нескольких символов без амперсанда. Этот «жадный квантификатор» (+) будет сопоставлять и сопоставлять и сопоставлять пробелы и видимые символы в нескольких строках, пока не найдет следующий & или конец строки! ... явно не то, что вы хотите.

Если вы хотите убедиться, что нет символов &, ?, #, вы можете использовать ([^&?#]+). Однако это тоже может потреблять слишком много, потому что, если URL-адрес не содержит ни одного из этих символов, механизм регулярных выражений будет соответствовать слишком много.

Если вы не уверены в том, какие символы будут существовать, но знаете, что они будут «видимыми» символами, вы можете использовать \S+.

Наконец, вы можете добавить символы пробела к вашему «классу отрицательных символов» следующим образом: ([^&?#\s]+). Используя этот последний, вы можете сразу же следовать за ним с помощью \S*, который будет соответствовать / потреблять ноль или более конечных видимых символов - это гарантирует что весь URL заменен и что вы получаете только то «белое мясо», которое ищете.

Другие вопросы по теме