Как сделать так, чтобы утверждение регулярного выражения PHP применялось ко всему шаблону при поиске адресов электронной почты? - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь найти адреса электронной почты в тексте, опубликованном пользователями на моем онлайн-форуме, и изменить их на код доски объявлений (BBCode).Например:

example@yahoo.com 

станет:

[mail]exmaple@yahoo.com[/mail]  

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

[mail]exmaple@yahoo.com[/mail]

стало:

[mail][mail]exmaple@yahoo.com[/mail][/mail]

Поэтому мне нужно добавить отрицательное утверждение с задним числом в мое регулярное выражение, чтобы гарантировать, что адрес электронной почтыперед ним не стоят символы [mail] (или просто]).

Я использую PHP-код:

$pattern = '#(?<!])([a-zA-Z0-9_\-\.]*@\S+\.\w+)#';
$bbcode = '[mail]$1[/mail]';
preg_replace($pattern, $bbcode, $text);

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

[mail]example@yahoo.com[/mail]

Результат:

[mail]e[mail]xample@yahoo.com[/mail][/mail]

Таким образом, отрицательный взгляд назад находит [mail] e, но остальная часть адреса электронной почты xample @ yahoo.com все еще проверяет.Я полагаю, что это из-за того, как написан под-шаблон поиска адреса электронной почты, потому что он допускает любое количество символов перед @.

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

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

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

(?<!])\b([a-zA-Z0-9_\-\.]+@\S+\.\w+)(?!\[)

Демо

0 голосов
/ 05 марта 2019

Вы можете сопоставлять и пропускать подстроки между [mail] и [/mail] и соответствовать только шаблону электронной почты, который есть у вас во всех других контекстах:

$rx = '~\[mail].*?\[/mail](*SKIP)(*F)|[a-zA-Z0-9_.-]*@\S+\.\w+~si';
// Or, if the tag is `url`
// $rx = '~\[url(?:\s+[^]]*)?].*?\[/url](*SKIP)(*F)|[a-zA-Z0-9_.-]*@\S+\.\w+~si';
$text = preg_replace($rx, '[url=mailto:$0]$0[/url]', $text);

См. Демонстрационную версию regex .

Подробности

  • \[mail].*?\[/mail](*SKIP)(*F) - [mail], затем любые 0+ символов, как можно меньше, а затем [/mail], (*SKIP)(*F)отбрасывает совпадение и начинает следующий поиск с конца неудачного совпадения
  • | - или
  • [a-zA-Z0-9_.-]*@\S+\.\w+ - шаблон, подобный электронной почте.

$0 в шаблоне замены относится ко всему значению соответствия, нет необходимости переносить весь шаблон с использованием скобок.

ПРИМЕЧАНИЕ. Если регулярное выражение для извлечения электронной почты не работает должным образом, установите флажок InPHP, как мне извлечь несколько адресов электронной почты из блока текста и поместить их в массив? .

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