2010-11-23 4 views
2

J'ai besoin d'obtenir l'adresse email d'une ancre avec un attribut mailto avec regex.preg_match pour extraire mailto sur l'ancre

ce modèle: (.*)<a\s(.*?)(.*)\s*href\=['"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['"]>(.*)</a>(.*)

Travaux en autocar regex si cela ne fonctionne pas avec PHP.

code:

preg_match("'(.*)<a (.*?)(.*) *href\=['\"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['\"]>(.*)</a>(.*)'si", "<a href=\"mailto:[email protected]\"">Some email</a>", $matches); 

print_r($matches); 

Alors pourquoi doenst il fonctionne en php?

+0

Comme une note de côté: vous devrez ajouter '+' comme un personnage dans votre classe de personnage :([-a-z0-9 _] +) parce que certaines personnes les utilisent pour filtrer les déclencheurs dans les adresses e-mail, par exemple foo + [email protected] – Keng

+0

Tous ces '. *' entraîneront un comportement de performance horrible. – Gumbo

+0

note de côté: bien que rare, il est parfaitement acceptable d'avoir une adresse e-mail comme: hell.o \ @ world @ two.ats.com Vous feriez mieux de tirer pour une regex plus simple, à moins qu'il y ait un problème de sécurité avec le emails. Cela dépend de ce que vous faites avec em. – DampeS8N

Répondre

4

PHP’s PCRE nécessitent l'expression régulière à envelopper dans delimiters qui séparent le motif de modifiers facultatif. Dans ce cas, le premier caractère non alphanumérique est utilisé (c'est-à-dire '), de sorte que le motif est en réalité juste (.*)<a (.*?)(.*) *href\=[ et le reste est traité comme modificateur. Et c'est une expression régulière invalide car le [ n'est pas correctement échappé et les autres ne sont pas des modificateurs valides non plus.

Comme les autres l'ont déjà suggéré, vous pouvez résoudre ce problème en échappant à l'occurrence du délimiteur ' dans l'expression régulière ou en choisissant un délimiteur différent qui n'apparaît pas dans l'expression régulière. Mais à côté de ça, essayer d'analyser HTML avec des expressions régulières est très sujet aux erreurs. Dans votre cas, l'utilisation de ce nombre .* entraînera également un comportement de performance horrible (c'est juste dû à la façon dont les expressions régulières sont traitées).

Mieux utiliser un analyseur HTML approprié qui retourne un DOM qui peut être interrogé comme PHP’s DOM library:

$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); 
     } 
    } 
} 
+2

-1 Répondez à la question spécifique, _then_ lecture à propos de pourquoi DOM est meilleur.Il n'est peut-être pas anodin pour le demandeur de comprendre la nouvelle bibliothèque ou de refactoriser sa situation assez rapidement, peu importe à quel point nous pensons qu'il y a une meilleure façon de procéder. – Shabbyrobe

+0

@Shabbyrobe: J'ai ajouté une explication. – Gumbo

+0

+2! Bon travail. C'est une excellente réponse maintenant! – Shabbyrobe

1

Votre delimiter est une citation ', et il y a certains cas de celui-ci dans la regex:

preg_match("'(.*)<a (.*?)(.*) *href\=['\"]mailto:([-a-z0-9_]+)@([a-z0-9-]+).([a-z]+)['\"]>(.*)</a>(.*)'si", "<a href=\"mailto:[email protected]\"">Some email</a>", $matches); 
            ^           ^

leur échapper (i.e. .: \') ou changer votre delimiter.

0
if (preg_match('#<a\s.*?href=[\'"]mailto:([A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,6})[\'"].*?>.*?</a>#i', $subject, $regs)) { 
    $result = $regs[0]; 
} else { 
    $result = ""; 
}
+0

This fails for something like '…'. – Gumbo