【问题标题】:Regex for email address not accept '&' before 'dot'电子邮件地址的正则表达式在“点”之前不接受“&”
【发布时间】:2013-05-20 14:01:35
【问题描述】:

这是在 phpbb 中验证电子邮件地址的功能的一部分。 我有一个有效的电子邮件地址

"pwd-p&r2.coop@..." 但不被验证接受。

有趣的是,当我尝试“pwd-pr2.co&op@...”(在“点”之后带有“&”)时

和“pwd-pr&2coop@...”(不带“点”)都是有效的,

但“pwd-pr&2.coop@...”(在“&”之后有“点”)不是。

我已经尝试更改正则表达式好几天了,但仍然不知道如何修复它以便它接受我的电子邮件地址。

function get_preg_expression($mode)
{
    switch ($mode)
    {
        case 'email':
        // Regex written by James Watts and Francisco Jose Martin Moreno
        // http://fightingforalostcause.net/misc/2006/compare-email-regex.php
        return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)';
    break;
    }
}

【问题讨论】:

  • & 不是正则表达式中的特殊字符,因此您不需要转义它
  • 我无法确认,对我来说它也匹配pwd-p&r2.coop@…。您使用什么正则表达式引擎(什么编程语言)?除了正则表达式之外,验证接受是否还有其他限制?
  • @ted:不。那里提出的正则表达式显然与 OP 的有效地址不匹配。不如看看davidcel.is/blog/2012/09/06/…
  • @Bergi,是的,误解了 OP;删除
  • @Bergi:该函数位于另一个 php 文件中的“functions.php”中。我认为这里的问题是'&'相对于'dot'的位置如果只有其中一个存在或'&'在'dot'后面,它们是有效的

标签: regex


【解决方案1】:

不应该使用正则表达式来验证电子邮件,这正是这个问题中发生的原因——它很复杂,几乎没有人能做对。

PHP 具有filter_var() 函数形式的内置电子邮件验证器。这通常是验证电子邮件的最佳选择。

这是一行代码,根本不需要任何复杂的正则表达式。

从以上链接复制的示例(即 PHP 手册):

<?php
$email_a = 'joe@example.com';
$email_b = 'bogus';

if (filter_var($email_a, FILTER_VALIDATE_EMAIL)) {
    echo "This (email_a) email address is considered valid.";
}
if (filter_var($email_b, FILTER_VALIDATE_EMAIL)) {
    echo "This (email_b) email address is considered valid.";
}
?>

希望对您有所帮助。

【讨论】:

  • 这对于 PHP 来说绝对是正确的(所以 +1),但它会在 OP 需要 phpBB 的情况下工作吗? AFAIK,phpBB 使用正则表达式处理大量验证,因此在这种情况下,正确的答案可能实际上不起作用。 OP,你能确认这符合你的需要吗?
  • @Spudley:filter_var() 确实很好用。我曾经这样做过。但是,我使用的是 phpBB 的代码,所以很难修复已经构建的所有内容。不过谢谢!
  • @sigpwned:你完全正确。我仍在尝试不同的正则表达式来解决这个问题。
【解决方案2】:

试试这个:

function get_preg_expression($mode)
{
    switch ($mode)
    {
        case 'email':
        // Regex written by James Watts and Francisco Jose Martin Moreno
        // http://fightingforalostcause.net/misc/2006/compare-email-regex.php
        // return '^(?:[\w!#$%&\'*+-\/=?^`{|}~]+\.)*(?:[\w!#$%&\'*+-\/=?^`{|}~]|&amp;)+$';
        return '(?:[\w!#$%&\'*+-\/=?^`{|}~]+\.)*(?:[\w!#$%&\'*+-\/=?^`{|}~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)';
    break;
    }
}

我取消了前括号表达式中不需要转义的字符。这似乎成功了。更具体地说,我留下的唯一转义字符是:(a)',由于 PHP 字符串转义语法,以及(b)/,因为我使用 / 作为 PHP 的 preg 分隔符。

不幸的是,我不知道为什么这种逃避有帮助。但是,最好的做法是只逃避需要逃避的东西,所以我根据你“应该”做的事情得出了解决方案,所以我很乐意分享。答案并不令人满意,但至少它似乎有效。

这是我用于测试的测试工具,以防万一有用,加上匹配性:

function get_preg_expression($mode)
{
    switch ($mode)
    {
        case 'email':
        // Regex written by James Watts and Francisco Jose Martin Moreno
        // http://fightingforalostcause.net/misc/2006/compare-email-regex.php
        // return '^(?:[\w!#$%&\'*+-\/=?^`{|}~]+\.)*(?:[\w!#$%&\'*+-\/=?^`{|}~]|&amp;)+$';
        return '(?:[\w!#$%&\'*+-\/=?^`{|}~]+\.)*(?:[\w!#$%&\'*+-\/=?^`{|}~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)';
    break;
    }
}

var_dump(preg_match('/' . get_preg_expression('email') . '/', 'pwd-pr&2coop@hello.com')); // Matches
var_dump(preg_match('/' . get_preg_expression('email') . '/', 'pwd-pr&2.coop@hello.com')); // Matches
var_dump(preg_match('/' . get_preg_expression('email') . '/', 'pwd-p&r2.coop@hello.com')); // Matches
var_dump(preg_match('/' . get_preg_expression('email') . '/', 'hello')); // Does not match
var_dump(preg_match('/' . get_preg_expression('email') . '/', 'hello@world')); // Does not match
var_dump(preg_match('/' . get_preg_expression('email') . '/', 'hello@world.com')); // Matches

【讨论】:

  • 几分钟前我没有看到你的回答。我刚刚测试了你的正则表达式。它工作得很好。谢谢!
猜你喜欢
  • 2022-01-09
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 2011-10-14
相关资源
最近更新 更多