preg_match to extract mailto on anchor

2019-02-19 22:52发布

I need to get the email adress from an anchor with a mailto attribute with regex.

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

Works in regex coach though it doesnt work with PHP.

Code:

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

So why doenst it work in php?

3条回答
Evening l夕情丶
2楼-- · 2019-02-19 23:38

Your delimiter is a quote ', and there are some instances of it in the 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 them (i.e.: \') or change your delimiter.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-02-19 23:42

PHP’s PCRE require the regular expression to be wrapped into delimiters that separate the pattern from optional modifiers. In this case the first non-alphanumeric character is used (i.e. ') so the pattern is actually just (.*)<a (.*?)(.*) *href\=[ and the rest are treated as modifiers. And that is an invalid regular expression as the [ is not properly escaped and the rest are not valid modifiers neither.

As the others have already suggested, you can fix this by escaping any occurrence of the delimiter ' inside the regular expression or choose a different delimiter that does not appear in the regular expression.

But besides that, trying to parse HTML with regular expressions is very error prone. In you case using that many .* will also result in a horrible performance behavior (it’s just due to how regular expressions are processed).

Better use a proper HTML parser that returns a DOM that can be queried like 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);
        }
    }
}
查看更多
家丑人穷心不美
4楼-- · 2019-02-19 23:45
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 = "";
}
查看更多
登录 后发表回答