PHP регулярное выражение (preg_match_all) - найти все автономные ссылки - PullRequest
0 голосов
/ 09 мая 2019

У меня есть текст в виде:

Txx8xxTT<br><br><br>https://wwww.xxx.com<br><br />
<br />cxyc[link=http://www.example.com]link[/odkaz]
xxx<a href="http://www.example2.com">link2</a>

Я хочу проанализировать это с помощью preg_match_all, где в массиве результатов все автономные ссылки имеют отдельные индексы.В этом примере я хочу получить что-то вроде этого:

[0] => Txx8xxTT<br><br><br>
[1] => https://wwww.xxx.com
[2] => <br><br />
    <br />cxyc[link=http://www.example.com]link[/odkaz]
    xxx<a href="http://www.example2.com">link2</a>

(массив может быть отформатирован по-разному, меня не волнуют индексы, но я хочу, чтобы отдельные ссылки имели собственный индекс)

Я пытался использовать preg_match_all с (.[^ \<\[]*).Это почти работает, но я получаю результат по индексу [3] как <br>https://wwww.xxx.com, где я не хочу префикс <br>.

[0] => Txx8xxTT
[1] => <br>
[2] => <br>
[3] => <br>https://wwww.xxx.com
[4] => <br>
[5] => <br
[6] =>  /> 
[7] => <br
[8] =>  />cxyc
[9] => [link="http://www.example.com"]link
[10] => [/odkaz]xxx
[11] => <a
[12] =>  href="http://www.example2.com">link2
[13] => </a>

Ответы [ 2 ]

3 голосов
/ 09 мая 2019

Вероятно, лучше всего:

  1. Анализировать ваш ввод через анализатор HTML / DOM
  2. Использовать DOM / XPath для поиска текстовых узлов
  3. Извлечь URL, используяregex

Пример 1 и 2 можно найти здесь: https://stackoverflow.com/a/6399988/406712

Тогда для вашего регулярного выражения рассмотрите "отрицательный взгляд назад", чтобы исключить ссылку, которая начинается с "[ссылка= ":

Использование

preg_match_all('/(?<!\[link=)\bhttps?:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[A-Z0-9+&@#\/%=~_|]/i', $subject, $result, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($result[0]); $i++) {
    # Matched text = $result[0][$i];
}

Регулярное выражение

(?<!\[link=)\bhttps?://[-A-Z0-9+&@#/%?=~_|!:,.;]*[A-Z0-9+&@#/%=~_|]

Визуализация

Regex Visualization

PS.если вы собираетесь изменять ввод HTML, используйте для этого методы DOM.

2 голосов
/ 09 мая 2019

См. Мой комментарий выше, объясняющий ужас разбора html с регулярным выражением.Это действительно не лучший подход.DOMDocument может быть лучшей идеей.

Если вы просто хотите получить массив ссылок, вы можете попробовать это.Однако я ничего не гарантирую.

#https?:\/\/[a-z1-9\.]+#

Это возвращает:

Match 1
Full match  20-40   https://wwww.xxx.com
Match 2
Full match  67-89   http://www.example.com
Match 3
Full match  115-138 http://www.example2.com

https://regex101.com/r/Sh5CTa/1

ОБНОВЛЕНИЕ, так как вы не хотите href = или ссылку =, вы можете попробовать это?

#>(?<link>https?:\/\/[a-z1-9\.]+)<#

Используется именованная группа захвата, поэтому это будет $ match ['link']

https://regex101.com/r/Sh5CTa/2

...