preg_match para extrair o correio em âncora
-
27-09-2019 - |
Pergunta
Preciso obter o endereço de e -mail de uma âncora com um atributo de e -mail com regex.
esse padrão: (.*)<a\s(.*?)(.*)\s*href\=['"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['"]>(.*)</a>(.*)
Funciona no Regex Coach, embora não funcione com o PHP.
Código:
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);
Então, por que funciona no PHP?
Solução
PCRE do PHP exigir que a expressão regular seja envolvida delimitadores que separam o padrão de opcional modificadores. Nesse caso, o primeiro personagem não alfanumérico é usado (ou seja, '
) então o padrão é realmente apenas (.*)<a (.*?)(.*) *href\=[
e o restante é tratado como modificadores. E essa é uma expressão regular inválida como o [
não é escapar corretamente e o restante também não são modificadores válidos.
Como os outros já sugeriram, você pode consertar isso escapar de qualquer ocorrência do delimitador '
Dentro da expressão regular ou escolha um delimitador diferente que não apareça na expressão regular.
Mas, além disso, tentar analisar HTML com expressões regulares é muito propenso a erros. No seu caso usando tantos .*
também resultará em um comportamento de desempenho horrível (é apenas devido à maneira como as expressões regulares são processadas).
Melhor usar um analisador HTML adequado que retorne um DOM que pode ser consultado como Biblioteca Dom do 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);
}
}
}
Outras dicas
Seu delimitador é uma citação '
, e há alguns casos no 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);
^ ^
Escape deles (ou seja: \'
) ou altere seu delimitador.
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 = "";
}