2010-11-23 10 views
2

Ich brauche die E-Mail-Adresse von einem Anker mit einem mailto-Attribut mit Regex.preg_match zum Extrahieren von mailto auf Anker

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

Arbeiten in regex Trainer obwohl es mit PHP nicht funktioniert.

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

Also, warum es in php doenst arbeiten?

+0

Als Randbemerkung: Sie hinzufügen müssen '+' als ein Zeichen in Ihrer Zeichenklasse :([-a-z0-9 _] +) weil einige Leute sie zum Filtern von Triggern in E-Mail-Adressen verwenden, zB [email protected] – Keng

+0

All diese '. *' werden zu einem schrecklichen Leistungsverhalten führen. – Gumbo

+0

Randnotiz: Obwohl selten, ist es durchaus akzeptabel, eine E - Mail - Adresse wie: hell.o \ @ world @ two.ats.com Sie können besser für eine einfachere Regex schießen, es sei denn, es gibt einige Sicherheitsbedenken mit der E-Mails. Hängt davon ab, was Sie mit em machen. – DampeS8N

Antwort

4

PHP’s PCRE erfordern den regulären Ausdruck in delimiters gewickelt werden, die das Muster von optionalen modifiers trennen. In diesem Fall wird das erste nicht-alphanumerische Zeichen verwendet (d. H. '), so dass das Muster tatsächlich nur (.*)<a (.*?)(.*) *href\=[ ist und der Rest als Modifizierer behandelt wird. Und das ist ein ungültiger regulärer Ausdruck, da die [ nicht ordnungsgemäß maskiert ist und der Rest auch keine gültigen Modifikatoren sind.

Wie die anderen bereits vorgeschlagen haben, können Sie dies beheben, indem Sie jedes Vorkommen des Trennzeichens ' innerhalb des regulären Ausdrucks umgehen oder ein anderes Trennzeichen wählen, das nicht im regulären Ausdruck erscheint.

Aber abgesehen davon ist der Versuch, HTML mit regulären Ausdrücken zu analysieren, sehr fehleranfällig. In Ihrem Fall wird die Verwendung von vielen .* auch zu einem schrecklichen Leistungsverhalten führen (es liegt nur daran, wie reguläre Ausdrücke verarbeitet werden).

besser verwenden, um einen richtigen HTML-Parser, der eine DOM zurückgibt, wie PHP’s DOM library abgefragt werden kann:

$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. Beantworten Sie die spezifische Frage, _then_ lecture warum DOM besser ist.Es mag für den Fragesteller nicht trivial sein, die neue Bibliothek zu verstehen oder ihre Situation schnell genug zu überdenken, egal wie sehr wir glauben, dass es einen besseren Weg gibt. – Shabbyrobe

+0

@Shabbyrobe: Ich habe eine Erklärung hinzugefügt. – Gumbo

+0

+2! Gute Arbeit. Es ist jetzt eine tolle großartige Antwort! – Shabbyrobe

1

Ihr Trennzeichen ist ein Zitat ', und es gibt einige Beispiele davon in der 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); 
            ^           ^

sie Flucht (d.h .: \') oder Ihr Trennzeichen ändern.

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