用于多个电子邮件地址替换的正则表达式

时间:2011-09-24 16:46:57

标签: php regex preg-replace preg-match

好的,这就是我的情况。我有一个由WordPress运行的网站。我需要确保电子邮件混淆,因此安装了一个名为“Graceful Email Obfuscation”的插件。这已经很好了。问题是,如果有人不遵守它为输入电子邮件地址指定的规则(即[email] test@example.com [/email]),我想要收集邮件。

以下正则表达式非常适合抓取所有电子邮件但我不希望它触及正确写为[email]test@example.com[/email]的那些电子邮件。我需要添加什么?

// Match any a href="mailto: AND make it optional
$monster_regex = '`(\<a([^>]+)href\=\"mailto\:)?';  

// Match any email address
$monster_regex .= '([^0-9:\\r\\n][A-Z0-9_]+([.][A-Z0-9_]+)*[@][A-Z0-9_]+([.][A-Z0-9_]+)*[.][A-Z]{2,4})'; 

// Now include all its attributes AND make it optional
$monster_regex .= '(\"*\>)?';

// Match any information enclosed in the <a> tag AND make it optional
$monster_regex .= '(.*)?'; 

// Match the closing </a> tag AND make it optional
$monster_regex .= '(\<\/a\>)?`'; 

$monster_regex .= 'im'; // Set the modifiers

preg_match_all($monster_regex, $content, $matches, PREG_SET_ORDER);

我的测试输入是:

<a href = "test@example.com">Tester</a>
test@example.com
<a href = "test@hotmail.com">Hotmail Test</a>
[email]test@example.com]

我得到的输出是:

(
    [0] => Array
        (
            [0] => <a href="mailto:test@example.com">Tester</a>

            [1] => <a href="mailto:
            [2] =>  
            [3] => test@example.com
            [4] => 
            [5] => 
            [6] => ">
            [7] => Tester</a>

        )

    [1] => Array
        (
            [0] => test@example.com

            [1] => 
            [2] => 
            [3] => test@example.com
            [4] => 
            [5] => 
            [6] => 
            [7] => 

        )

    [2] => Array
        (
            [0] => <a href="mailto:test@hotmail.com">Hotmail Test</a>

            [1] => <a href="mailto:
            [2] =>  
            [3] => test@hotmail.com
            [4] => 
            [5] => 
            [6] => ">
            [7] => Hotmail Test</a>

        )

    [3] => Array
        (
            [0] => [email]test@example.com[/email]

            [1] => 
            [2] => 
            [3] => [email]test@example.com
            [4] => 
            [5] => 
            [6] => 
            [7] => [/email]

        )
)

提前致谢。

1 个答案:

答案 0 :(得分:0)

所以你想要匹配任何看起来像电子邮件地址的东西,除非它已经包含在[email]...[/email]标签中了吗?试试这个:

'%(?>\b[A-Z0-9_]+(?:\.[A-Z0-9_]+)*@[A-Z0-9_]+(?:\.[A-Z0-9_]+)*\.[A-Z]{2,4}\b)(?!\s*\[/email\])%i'

注意:这个答案只解决了如何匹配没有包含更大结构的东西的问题。我不打算就如何(或是否)将电子邮件地址与正则表达式进行匹配进行辩论。我只是从问题中提取核心正则表达式,用word boundaries\b)括起来并将其包裹在atomic group(?>...))中。

找到潜在匹配后,negative lookahead断言地址后面没有结束[/email]标记。假设标签已正确配对,则表示该地址已正确标记。如果他们没有正确配对,那么抓住它就是插件的工作。


当我在这里时,我想对你的正则表达式提出一些评论:

  • 范围表达式A-z出现在您的某些角色类中。可能只是一个错字,但有些人用它作为匹配大写或小写字母的习语。这是一个错误,因为它还匹配几个标点字符,其代码点恰好位于两个字母范围之间。 (我在编辑问题时修正了。)

  • 字符<>:"@=/包含正则表达式没有特殊含义,也不需要转义。它并没有伤害任何东西,但是已经足够难以阅读的正则表达式;为什么扔掉一堆你不需要的反斜杠和方括号?

  • (.*)?中的问号属于parens:(.*?)。这样,它会在下一个</a>之前不情愿地匹配所有内容。如果没有什么可以匹配的话,它什么都不匹配。使其成为可选项不仅是多余的,而且可能导致serious performance penalties