找到模式匹配失败的第一个位置。

时间:2014-02-19 07:10:17

标签: php regex email-validation

我正在尝试查找用户在输入电子邮件ID时遇到的常见错误。我总是可以使用PHP电子邮件过滤器验证EMAIL

$email = "someone@exa mple.com";

if(!filter_var($email, FILTER_VALIDATE_EMAIL))
{
  echo "E-mail is not valid";
}
else
{
 echo "E-mail is valid";
}

或模式匹配

$email = test_input($_POST["email"]);
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))
{
  $emailErr = "Invalid email format"; 
}

我同意这些不是验证电子邮件的完整证据方式。但是他们应该捕获80%的病例。

我想要的是 - 哪个位置的电子邮件无效?如果它是一个空间,用户进入空间的位置。或者因为“。”而失败了。到底?

任何指针?

-Ajay

PS:我见过有关电子邮件验证的其他帖子。我可以增加复杂性并使其100%。这里关注的是捕获人们在输入电子邮件ID时所犯的最常见错误。

4 个答案:

答案 0 :(得分:1)

这很困难,因为有时并不总是单个字符会使电子邮件地址无效。您提供的示例可以通过以下方式轻松解决:

$position = strpos('someone@exa mple.com', ' ');

然而,似乎你对一个包罗万象的解决方案不感兴趣,而是能够捕获大多数基于字符的错误。我将采用使用正则表达式的方法,但以子模式捕获电子邮件地址的每个部分以进行进一步验证。例如:

$matches = null;
$result = preg_match("/(([\w\-]+)\@([\w\-]+)\.([\w\-]+))/", $email, $matches);
var_dump($matches);

通过在子模式中捕获正则表达式验证的各个部分,您可以进一步深入到每个部分并运行相似或不同的测试以确定用户出错的位置。例如,您可以尝试将电子邮件地址的TLD与白名单进行匹配。当然,在Zend或Symfony这样的框架中还有更强大的电子邮件验证器可以更具体地告诉您为什么电子邮件地址无效,但是要知道哪个特定字符位置有问题(假设它是一个字符位于我认为战术的组合效果最好。

答案 1 :(得分:1)

我无法在Java中知道报告正则表达式失败的地方。您可以做的是开始构建一组可以检查的常见错误(如Manu所述)(这可能会也可能不会使用正则表达式)。然后分类为这些已知错误和其他',计算每个错误的频率。当一个'其他'发生错误,开发一个可以捕获它的正则表达式。

如果您需要一些帮助来追踪正则表达式失败的原因,您可以使用regexbuddy等实用程序,如this answer所示。

答案 2 :(得分:0)

只需自行执行一些检查:

指向最后:

if(substr($email, -1) == '.')
    echo "Please remove the point at the end of you email";

发现空间:

$spacePos = strpos($email, ' ');
if(spacePos  !== false)
   echo  "Please remove the space at pos: ".$spacePos;

等等......

答案 3 :(得分:0)

首先,我想说你的例子失败的原因不是空间。缺少'。'在前一部分,在后一部分缺乏'@'。 如果输入

'someone@example.co m''s omeone@example.com',它会成功。

所以你可能需要'以'开头'和'结束'模式来严格检查。

现在没有方法来检查正则表达式匹配失败的位置,因为我知道因为只检查给出了匹配,但是如果你真的想找到它,我们可以通过'分解'正则表达式来做一些事情。 / p>

让我们来看看你的示例检查。

preg_match ("/^[\w\-]+\@[\w\-]+\.[\w\-]+$/",'someone@example.com.');

如果失败,您可以检查其“子表达式”的成功位置,并找出问题所在:

$email = "someone@example.com.";
if(!preg_match ("/^[\w\-]+\@[\w\-]+\.[\w\-]+$/",$email)){ // fails because the final '.'
    if(preg_match("/^[\w\-]+\@[\w\-]+\./",$email,$matches)){ // successes

        $un_match = "[\w\-]+"; // What is taken from the tail of the regular expression.
        foreach ($matches as $match){
            $email_tail = str_replace($match,'',$email); // The email without the matching part. in this case : 'com.'
            if(preg_match('/^'.$un_match.'/',$email_tail,$match_tails)){ // Check and delete the part that tail match the sub expression. In this example, 'com' matches /[\w\-]+/ but '.' doesn't. 
                $result = str_replace($match_tails[0],'',$email_tail);
            }else{
                $result = $email_tail;
            }
        }
    }
}
var_dump($result); // you will get the last '.'

如果您理解上面的示例,那么我们可以使我们的解决方案更常见,例如,如下所示:

$email = 'som eone@example.com.';
    $pattern_chips = array(
        '/^[\w\-]+\@[\w\-]+\./' => '[\w\-]+',
        '/^[\w\-]+\@[\w\-]+/' => '\.',
        '/^[\w\-]+\@/' => '[\w\-]+',
        '/^[\w\-]+/' => '\@',
    );
    if(!preg_match ("/^[\w\-]+\@[\w\-]+\.[\w\-]+$/",$email)){
      $result = $email;
      foreach ($pattern_chips as $pattern => $un_match){
        if(preg_match($pattern,$email,$matches)){
          $email_tail = str_replace($matches[0],'',$email);
          if(preg_match('/^'.$un_match.'/',$email_tail,$match_tails)){
            $result = str_replace($match_tails[0],'',$email_tail);
          }else{
            $result = $email_tail;
          }
          break;
        }
      }
      if(empty($result)){
        echo "There has to be something more follows {$email}";
      }else{
        var_dump($result);
      }
    }else{
      echo "success";
    }

你会得到输出:

string ' eone@example.com.' (length=18)