PHP Regex - отрицает совпадение, если оно содержит слово (строку)

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

Предполагая, что у меня есть эта строка:

[url=http://www.example.com]this url BB tag should match[/url]
[url=http://www.example.com][spoiler]this url BB tag shouldn't match[/spoiler][/url]

Изменить: более подробная строка, которая не должна возвращать совпадение для отладки:

[url=http://www.example.com]Lorem[spoiler]this url BB tag shouldn't match[/spoiler]Ipsum[/url]

И текущий шаблон регулярного выражения:

#\[url=([\w]+?://.*?)\]([^?\n\r\t].*?)\[/url\]#is

Изменить: я использую следующее регулярное выражение (без # и #is) для его отладки в Regex Buddy:

\[url=([\w]+?://.*?)\]([^?\n\r\t].*?)\[/url\]

(эти два регулярных выражения должны иметь такой же эффект на мое приложение, поскольку я могу легко адаптировать его, поэтому работайте с последним, если это имеет больше смысла)

Соответствует обеим строкам в строке. Я хочу, чтобы он не возвращал совпадение, когда между [url=xxxx://yyyy] и [/url] есть строка [spoiler].

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

Любая помощь приветствуется.


person Fabrício Matté    schedule 18.04.2012    source источник


Ответы (1)


Это должно решить проблему.

'#\[url=([^\]]+)\](?!\[spoiler\])(.*?)\[/url\]#'
person Rezigned    schedule 18.04.2012
comment
Он все еще возвращает совпадение для [url=http://www.google.com][spoiler][/spoiler][/url] в моих тестерах php и regex. - person Fabrício Matté; 18.04.2012
comment
Вот мой тест preg_match('#\[url=([^\]]+)\](?!\[spoiler\])(.*?)\[/url\]#', '[url=http://www.google.com][spoiler][/spoiler][/url]', $m); print_r($m); Он ничего не возвращает (чего вы и хотите). - person Rezigned; 18.04.2012
comment
Ой, извините, для моего комментария выше он фактически не возвращает совпадение для вашего регулярного выражения, однако, если я добавлю какой-либо символ перед [spoiler], он вернет совпадение: [url=http://wwww.google.com]Hi[spoiler][/spoiler][/url] - person Fabrício Matté; 18.04.2012
comment
Добавление. * Внутри опережающего просмотра, кажется, помогает, я отлажу его и опубликую результаты. - person Fabrício Matté; 18.04.2012
comment
Хорошо, (?!.*\[spoiler\]) lookahead делает свое дело, но я все же хотел сохранить итерацию \ w и: // проверить этот шаблон, так что вот последнее регулярное выражение: #\[url=(?=[^_\W]+?://)([^\]]+)\](?!.*\[spoiler\])(.*?)\[/url\]#i. Спасибо за помощь. - person Fabrício Matté; 18.04.2012
comment
О, я обнаружил исключение, [url=xxxx://yyyy]zzzz[/url][spoiler][/spoiler] не вернет никакого совпадения с регулярным выражением выше, вот исправленная версия, если у кого-то когда-либо возникнет аналогичная проблема при редактировании шаблона phpbb2: #\[url=(?=[^_\W]+?://)([^\]]+)\](?!.*?\[spoiler\].*?\[/url\])(.*?)\[/url\]#i - person Fabrício Matté; 18.04.2012