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

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

'~(?:<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'

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

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

EDIT:

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

$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>'
);

1 Ответ

0 голосов
/ 04 ноября 2018

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

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

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

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

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

...