preg_match для извлечения mailto на якоре
-
27-09-2019 - |
Вопрос
Мне нужно получить адрес электронной почты с якоря с атрибутом Mailto с Regex.
Этот шаблон: (.*)<a\s(.*?)(.*)\s*href\=['"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['"]>(.*)</a>(.*)
Работает в тренере Regex, хотя он не работает с PHP.
Код:
preg_match("'(.*)<a (.*?)(.*) *href\=['\"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['\"]>(.*)</a>(.*)'si", "<a href=\"mailto:someemail@ohio.com\"">Some email</a>", $matches);
print_r($matches);
Так почему же, что он работает в PHP?
Решение
PHRE PHRE требуют, чтобы регулярное выражение было завернуто в разделители это отделить шаблон из необязательного модификаторы. Отказ В этом случае используется первый не буквенно-цифровой символ (т.е. '
) так что шаблон на самом деле просто (.*)<a (.*?)(.*) *href\=[
И остальные рассматриваются как модификаторы. И это неверное регулярное выражение как [
неправильно избежается, а остальные не являются действительными модификаторами.
Как и другие уже предложили, вы можете исправить это, избегая любого возникновения разделителя '
Внутри регулярного выражения или выберите другой разделитель, который не отображается в регулярном выражении.
Но кроме того, пытаясь анализировать HTML с регулярными выражениями, очень подвержены ошибкам. В вашем случае, используя это много .*
Также приведет к ужасному поведению эффективности (он только из-за того, насколько регулярно обрабатываются регулярные выражения).
Лучше Используйте правильный Parser HTML, который возвращает DOM, который может быть запрошен, как Библиотека Dom PHP:
$doc = new DomDocument();
$doc->loadHTML($str);
foreach ($doc->getElementsByTagName("a") as $a) {
if ($a->hasAttribute("href")) {
$href = trim($a->getAttribute("href"));
if (strtolower(substr($href, 0, 7)) === 'mailto:') {
$components = parse_url($href);
}
}
}
Другие советы
Ваш разделитель - цитата '
, И есть некоторые экземпляры этого в Regex:
preg_match("'(.*)<a (.*?)(.*) *href\=['\"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['\"]>(.*)</a>(.*)'si", "<a href=\"mailto:someemail@ohio.com\"">Some email</a>", $matches);
^ ^
Избежать их (т.е. \'
) Или измените свой разделитель.
if (preg_match('#<a\s.*?href=[\'"]mailto:([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6})[\'"].*?>.*?</a>#i', $subject, $regs)) {
$result = $regs[0];
} else {
$result = "";
}