2

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

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

在正则表达式教练中工作,尽管它不适用于 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 中工作呢?

4

3 回答 3

5

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

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

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

最好使用适当的 HTML 解析器,它返回可以像PHP 的 DOM 库一样查询的 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);
        }
    }
}
于 2010-11-23T16:55:45.647 回答
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);
                                      ^                                              ^

转义它们(即:)\'或更改分隔符。

于 2010-11-23T16:43:01.980 回答
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 = "";
}
于 2010-11-23T16:43:27.490 回答