preg_match在锚点上提取mailto

时间:2010-11-23 16:38:46

标签: php regex anchor preg-match mailto

我需要从带有正则表达式的mailto属性的锚点获取电子邮件地址。

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

在regex教练中工作虽然它不适用于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 个答案:

答案 0 :(得分:5)

PHP’s PCRE要求将正则表达式包装到delimiters中,以便将模式与可选modifiers分开。在这种情况下,使用第一个非字母数字字符(即'),因此模式实际上只是(.*)<a (.*?)(.*) *href\=[,其余的被视为修饰符。这是一个无效的正则表达式,因为[未正确转义,其余的也不是有效的修饰符。

正如其他人已经建议的那样,你可以通过在正则表达式中转义任何出现的分隔符'来解决这个问题,或者选择一个不出现在正则表达式中的不同分隔符。

但除此之外,尝试使用正则表达式解析HTML非常容易出错。在你的情况下,使用那么多.*也会导致一种可怕的性能行为(这只是由于正则表达式的处理方式)。

更好地使用适当的HTML解析器来返回可以像PHP’s DOM library一样查询的DOM:

$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 :(得分:1)

您的分隔符是引用',正则表达式中有一些实例:

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

逃避它们(即:\')或更改分隔符。

答案 2 :(得分:0)

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 = "";
}