【问题标题】:preg_match to extract mailto on anchorpreg_match 在锚点上提取 mailto
【发布时间】:2011-05-14 14:13:46
【问题描述】:

我需要从带有正则表达式的 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 中工作呢?

【问题讨论】:

  • 附带说明:您需要在角色类中添加 + 作为角色 :([-a-z0-9_]+) 因为有些人使用它们来过滤触发器电子邮件地址,例如 foo+bar@devnull.nz
  • 所有这些.* 将导致可怕的性能行为。
  • 旁注:虽然很少见,但拥有像这样的电子邮件地址是完全可以接受的:hell.o\@world@two.ats.com 您最好选择更简单的正则表达式,除非电子邮件存在一些安全问题。取决于你用 em 做什么。
  • @Gumbo 会 .*$ 做吗?基本上都到行尾?
  • @DampeS8N:不,hell.o\@world@example.com 无效(\‍@ 都无效)。但是"hell.o@world"@example.com 是有效的。

标签: php regex anchor preg-match mailto


【解决方案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】:
    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 = "";
    }

    【讨论】:

    • 这对于&lt;a name="…"&gt;…&lt;/a&gt;&lt;map name="…"&gt;&lt;area href="…" alt="…"&gt;&lt;/map&lt;a href="mailto:user@example.com"&gt;…&lt;/a&gt;之类的东西会失败。
    【解决方案3】:

    PHP’s PCRE 要求将正则表达式包装到delimiters 中,将模式与可选的modifiers 分开。在这种情况下,使用了第一个非字母数字字符(即'),因此模式实际上只是(.*)&lt;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。回答具体问题,然后讲座为什么 DOM 更好。无论我们多么认为有更好的方法,询问者理解新库或足够快地重构他们的情况可能都不是一件容易的事。
    • @Shabbyrobe:我已经添加了解释。
    猜你喜欢
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多