【问题标题】:Using regex to extract username from email address使用正则表达式从电子邮件地址中提取用户名
【发布时间】:2010-12-20 09:08:05
【问题描述】:

我的文本字符串如下所示:

johndoe@domain.com (John Doe)

我只需要得到@之前的部分,没有别的。如果重要的话,文本来自一个简单的 XML 对象。

我的代码如下所示:

$authorpre = $key->{"author"};
$re1 = '((?:[a-z][a-z]+))';

if ($c = preg_match_all ("/".$re1."/is", $authorpre, $matches))
{
    $author = $matches[1][0];
}

有时用户名可能在 @ 符号前有数字或下划线,这似乎是正则表达式停止的地方。

【问题讨论】:

  • 您的正则表达式有一个外部捕获组() 和一个内部非捕获组(?:)。考虑到您想要捕获内部的内容,内部非捕获组可能是不必要的。 [a-z] 表示捕获小写字母。 [a-z]+ 表示捕获 1 个或多个小写字母。因此,您的表达式有效地意味着捕获任何长度为 2 个或更多小写字母的内容。如果您将 ^ 放在表达式的最前面,它将确保匹配只发生在文本的 开头 处。
  • 恐怕不会很有趣。您可能想要测试的一些示例字符串:"John Doe"@example.com (John Doe)"(>'.')>"@example.com (John Doe)foo@[192.168.2.1] (John Doe)^.^@example.com (John Doe)"a@b@c"@example.com (John Doe)"。是的,这些都是有效的电子邮件地址 :-)
  • @Johannes: "a@b@c"@example.com (John Doe) 真的允许吗?这确实使事情变得复杂......
  • Welbog: en.wikipedia.org/wiki/E-mail_address ... 你可以引用本地部分,否则不允许使用字符。

标签: php regex preg-match


【解决方案1】:

匹配并捕获任何字符直到到达@ 字符的正则表达式:

([^@]+)

这似乎正是您所需要的。它将处理电子邮件地址的各种怪异变化。


我不知道为什么Ben James 删除了他的答案,因为我觉得它比我的好。我要把它贴在这里(除非他取消删除他的答案):

为什么使用正则表达式而不是字符串函数?

$parts = explode("@", "johndoe@domain.com");
$username = $parts[0];

在这种情况下,您根本不需要正则表达式。我个人认为使用explode 是一个更好的选择。


正如Johannes Rössel 在 cmets 中指出的那样,电子邮件地址解析相当复杂。如果您想 100% 确定您将能够处理任何技术上有效的电子邮件地址,那么您将不得不编写一个能够正确处理引用的例程,因为我的答案中列出的两种解决方案都会窒息地址如"a@b"@example.com。可能有一个库可以为您处理这种解析,但我不知道。

【讨论】:

  • 取决于你的正则表达式的强度,我个人喜欢爆炸功能。非常适合您的需求。
  • 电子邮件地址"a@b"@example.com是什么?
  • 乐趣永远不会以电子邮件地址中的源路由结束:remote.org/jochen/mail/info/address.html
  • last @ 之前采取一切措施,是的。除非 Jane Doe 提出了使用 "j@nedoe"@example.com (J@ne Doe) 的好主意...
  • 你的正则表达式 sn-p "[^"]*" 不能正确匹配带引号的字符串,因为带引号的字符串可能包含转义的引号字符。例如,"contains \"quotes\"" 是一个有效的地址。最好使用 "(?:[^"]|\\.)*"。
【解决方案2】:

@OP,如果您只想获取@之前的所有内容,只需使用字符串/数组方法。不需要复杂的正则表达式。在“@”上展开,然后删除作为域部分的最后一个元素

$str = '"peter@john@doe"@domain.com (John Doe)';
$s = explode("@",$str);
array_pop($s); #remove last element.
$s = implode("@",$s);
print $s;

输出

$ php test.php
"peter@john@doe"

【讨论】:

    【解决方案3】:

    也许这个变种比explode()慢一点,但它只需要一个字符串:

    $name = preg_replace('/@.*?$/', '', $email);
    

    【讨论】:

      【解决方案4】:
      <?php
      $email  = 'name@example.com';
      $domain = strstr($email, '@');
      echo $domain; // prints @example.com
      
      $user = strstr($email, '@', true); // As of PHP 5.3.0
      echo $user; // prints name
      ?>
      

      source

      【讨论】:

      • 比使用正则表达式更快!
      • 这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他带有引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
      【解决方案5】:

      我用preg_replace

      $email_username = preg_replace('/@.*/', '', $_POST['email']);
      

      【讨论】:

      • 这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他带有引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
      【解决方案6】:

      我的建议:

      $email = 'johndoe@domain.com';
      $username = substr($email, 0, strpos($email, '@'));
      
      // Output (in $username): johndoe
      

      【讨论】:

      • 这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他带有引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
      【解决方案7】:

      我会选择$author = str_replace(strrchr($authorpre, '@'), '', $authorpre);

      【讨论】:

        【解决方案8】:

        您可以先使用mailparse_rfc822_parse_addresses 解析地址,然后只提取地址规范而不使用任何显示名称。然后,您可以使用正则表达式 (.*)@ 提取 @ 之前的部分。

        【讨论】:

          【解决方案9】:

          使用这样的东西:

          list($username, $domain) = explode('@', $email . "@"); // ."@" is a trick: look note below
          

          使用此解决方案,您已经在一行中填充了两个带有电子邮件地址部分的变量。

          ."@":这样做是为了避免 list 命令出现严重错误,并确保explode 将根据需要产生至少两个变量。

          【讨论】:

          • 这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他带有引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
          【解决方案10】:

          如果有人还在寻找 2020 年 ..这里的正则表达式可以选择“@”之前的文本

          ^(\S+)(?=@)
          

          【讨论】:

          【解决方案11】:

          基本示例:

              $email = "linuxUser@IsGrand.com";
              if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
                  list($user, $domain) = explode('@', trim($email) . "@");
              } else {
                  echo "Unable to get account info ....";
              }
          

          复杂的例子: 像这样填充名字和姓氏字段:

          1) valid email ?  if yes get the two parts  user and domain.
          2) else set to something default etc.
          3) use the email address if we don't have a decoded value.
          

          代码:

              if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
                  list($fname, $lname) = explode('@', trim($email) . "@");
              } else {
                  $fname = "Xdefault";
                  $lname = "Ydefault";
              }
          
              $fname = (!empty($decoded['firstname'][0]))  ? $decoded['firstname'][0] : $fname ;
              $lname = (!empty($decoded['lastname'][0]))  ? $decoded['lastname'][0] : $lname ;
          

          【讨论】:

          • 这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他带有引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
          【解决方案12】:

          我还想在这里建议一个非正则表达式的解决方案,因为它在大多数情况下可能很有用:

          strstr('n.shah@xyz.co', '@', true)
          

          输出:

          n.shah

          【讨论】:

          • 这是多年前发布的 munjal 答案的精确副本。
          【解决方案13】:

          我已经测试了下面的模式,它给出了地址的开头部分,包括句点、加号和破折号。

          if ($c = preg_match_all ('^([\w\.\+\-]*)', $authorpre, $matches))
          

          【讨论】:

          • preg_match_all() 不仅不是最适合调用的正则表达式函数,而是在字符类中使用了不必要的转义和不必要的捕获组。此外,这将在 "()&lt;&gt;[]:,;@\\"!#$%&amp;'-/=?^_`{}| ~.a"@example.org 和其他引用 @ 本地人的电子邮件上失败。阅读更多:stackoverflow.com/a/38787343/2943403
          猜你喜欢
          • 2016-04-28
          • 2016-02-24
          • 1970-01-01
          • 2011-12-15
          • 2022-01-26
          • 2014-05-13
          • 2016-12-23
          • 2020-07-14
          • 1970-01-01
          相关资源
          最近更新 更多