Регулярное выражение PHP Perl – URL-адресу не предшествует знак равенства и возможны одинарные или двойные кавычки

Я пытаюсь создать регулярное выражение Perl, соответствующее URL-адресу, которому не предшествует знак равенства и одна одинарная или двойная кавычка (необязательно), игнорируя пробелы. Код ниже выдает ошибку: Warning: preg_replace(): Compilation failed: lookbehind assertion is not fixed length at offset 0

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

Например, в приведенном ниже коде в совпадениях должны выводиться http://www.url1.com/ и http://www.url3.com/, но не остальные URL-адреса. Как я могу это сделать? Код ниже выдает предупреждение и не заполняет переменную $matches.

PHP-код:

$html = "
http://www.url1.com/
= ' http://www.url2.com/
'http://www.url3.com/
<a href='http://www.url4.com/'>Testing1</a>
<img src='https://url5.com'>Testing2</a>";

$url_pregex = '((http(s)?://)[-a-zA-Z()0-9@:%_+.~#?&;//=]+)';
$pregex = '(?<!\\s*=\\s*[\'"]?\\s*)'.$url_pregex;

preg_match_all('`'.$pregex.'`i', $html, $matches);

echo "Matches<br><pre>";
var_export($matches);
echo "</pre>";

Perl Regex в PHP, используя ` вместо /:

'`(?<!\\s*=\\s*[\'"]?\\s*)((http(s)?://)[-a-zA-Z()0-9@:%_+.~#?&;//=]+)`i'

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

M. Eriksson 27.03.2024 20:54

@M.Eriksson К сожалению, допустил ошибку копирования и вставки и пропустил некоторые важные части. Теперь, я думаю, исправлено.

developer981 27.03.2024 21:32
Стоит ли изучать 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 и хотите разрабатывать...
0
2
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Один из способов обойти эту проблему — использовать чередование, первая часть которого соответствует URL-адресам, которым предшествует = (и необязательная кавычка), а вторая — просто соответствует URL-адресам, которые затем фиксируются. Это работает, потому что первая часть чередования всегда проверяется первой, и поэтому только URL-адреса, которым не предшествует =, будут захватываться второй частью чередования.

Для простоты я удалил группы захвата из вашего $url_pregex; если вы хотите, чтобы они были включены, вам нужно будет изменить номер группы $matches в этом коде, чтобы получить полные совпадения.

$html = "
http://www.url1.com/
= ' http://www.url2.com/
'http://www.url3.com/
<a href='http://www.url4.com/'>Testing1</a>
<img src = 'https://url5.com'>Testing2</a>";

$url_pregex = 'https?://[-a-zA-Z()0-9@:%_+.~#?&;//=]+';
$pregex = "\\s*=\\s*['\"]?\\s*$url_pregex|($url_pregex)";

preg_match_all('`' . $pregex . '`i', $html, $matches);

echo "Matches<br><pre>";
var_export(array_values(array_filter($matches[1])));
echo "</pre>";

Выход:

Matches<br><pre>array (
  0 => 'http://www.url1.com/',
  1 => 'http://www.url3.com/',
)</pre>

Демо на 3v4l.org

Обратите внимание, что вам нужно использовать preg_match_all, чтобы получить все совпадения в тексте.

Вам не следует раздувать выходной массив нежелательными/дисквалифицируемыми совпадениями, как показано в ответе Ника (тогда не будет необходимости очищать array_filter() и array_values()).

Чтобы использовать и выбрасывать спички, используйте (*SKIP)(*FAIL).

Я взял на себя смелость настроить ваш шаблон регулярного выражения, реализуя свой совет.

Код: (Демо)

$url_regex = 'https?://[-\w()@:%+.~#?&;/=]+';
$regex = "`\s*=\s*['\"]?\s*$url_regex(*SKIP)(*FAIL)|$url_regex`i";

var_export(preg_match_all($regex, $html, $matches) ? $matches[0] : []);

Выход:

array (
  0 => 'http://www.url1.com/',
  1 => 'http://www.url3.com/',
)

Если вы действительно пытаетесь проанализировать действительный HTML, то использование регулярного выражения вряд ли будет наиболее подходящим инструментом.

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