preg_match для извлечения mailto на якорь - PullRequest
2 голосов
/ 23 ноября 2010

Мне нужно получить адрес электронной почты от якоря с атрибутом mailto с регулярным выражением.

этот шаблон: (.*)<a\s(.*?)(.*)\s*href\=['"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['"]>(.*)</a>(.*)

Работает в regex coach, но не работает с 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?

Ответы [ 3 ]

5 голосов
/ 23 ноября 2010

PHP PCRE требует, чтобы регулярное выражение было обернуто в разделители , которые отделяют шаблон от необязательных модификаторов . В этом случае используется первый не буквенно-цифровой символ (т. Е. '), поэтому шаблон на самом деле просто (.*)<a (.*?)(.*) *href\=[, а остальные обрабатываются как модификаторы. И это недопустимое регулярное выражение, поскольку [ не экранировано должным образом, а остальные тоже не являются допустимыми модификаторами.

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

Но, кроме того, попытка анализа HTML с помощью регулярных выражений очень подвержена ошибкам. В вашем случае использование такого количества .* также приведет к ужасному поведению производительности (это просто из-за того, как обрабатываются регулярные выражения).

Лучше использовать правильный анализатор 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);
        }
    }
}
1 голос
/ 23 ноября 2010

Ваш разделитель - это кавычка ', и в регулярном выражении есть несколько его примеров:

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);
                                      ^                                              ^

Беги от них (т. Е. \') или меняй свой разделитель.

0 голосов
/ 23 ноября 2010
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 = "";
}
...