【问题标题】:Regex to find name in salutation of an email正则表达式在电子邮件的称呼中查找名称
【发布时间】:2012-10-16 17:47:31
【问题描述】:

我需要解析以下格式的电子邮件:

嗨,约翰·多伊,
这里还有一些文字。
还有更多、更多、更多的文字。
您的用户 ID 是:1234
您的激活 ID 是:5678910
更多文字出现在这里。

我正在寻找的正则表达式必须返回:

  1. 称呼中的名字(这里:“John Doe”)
  2. 用户 ID(此处:1234)
  3. 激活 ID(此处:5678910)

我尝试了以下正则表达式,但它返回了整个电子邮件;我相信我犯的错误是电子邮件正文的其余部分中还有其他逗号,因此冒号与所有逗号匹配。如果用户输入了一个奇怪的包含逗号的用户名,那么即使是称呼中的名字也可以包含逗号。

preg_match_all("/Hi (.*),/", $out, $match);

【问题讨论】:

  • 离开我的脑海 - 而不是 (.*) 尝试 (.+?)。你现在的那个是“贪婪的”。
  • 提示:使用三个正则表达式,一个用于"Hi <name>,",一个用于"Your user ID is: (\d+)",一个用于"Your activation ID is: (\d+)"

标签: php regex parsing email


【解决方案1】:

使用正则表达式

/Hi (.*?),\n.*?user ID is: (\d+).*?activation ID is: (\d+)/s
      ↑                      ↑                         ↑
  "John Doe"              "1234"                   "5678910"

PHP 代码:

$pattern = '/Hi (.*?),\n.*?user ID is: (\d+).*?activation ID is: (\d+)/s';
preg_match($pattern, $email, $m);
print("$m[1]\n$m[2]\n$m[3]");

输出:

John Doe
1234
5678910

检查this demo

【讨论】:

  • 我看到你正在缩短正则表达式...我更喜欢写尽可能短的正则表达式,而是使用更多的正则表达式(当然不能有任何功能损失,这不适用于长文本,其中通过完整文本的每次迭代都是昂贵的操作)。我发现长而复杂的正则表达式真的很难调试和分析,跟踪“一个子模式更改”(如果整个正则表达式失败)。也许您可以提及命名的子模式,它们会增加可读性。 (我会为您在此答案中所做的工作提供更多投票)
  • @Vyktor - 对于调试,您应该使用一些工具,并且不要将单个正则表达式模式拆分为多个模式,因为它会损害性能。
  • 我很清楚对性能的影响(我致力于从具有非常糟糕的 html 的网站中提取数据)。这就是为什么我提到它不应该在长文本上完成。长正则表达式 = 难读,高性能。更短的正则表达式 = 易于阅读,性能更差。我认为您需要的情况因情况而异。例如,即使用户 ID 不存在,他也可能需要保持脚本功能......在这种情况下,这个解决方案将不起作用(太糟糕了,他没有提到它是否应该提取尽可能多的数据或所有内容完全)。
  • 这对我不起作用;包含匹配项的数组为空。我发现电子邮件使用 HTML 换行符而不是换行符,所以我认为这会导致它不起作用。我尝试只使用第一部分:$pattern = '/Hi (.*?),/s'; 这有效,但它返回一个包含以下内容的数组:array ( 0 => 'Hi John Doe,', 1 => 'John Doe', )
【解决方案2】:

我会为每个字段使用一个正则表达式:

$match = array();
$regexs = array(
    '~Hi\s+(.+?),~', // notice ? -> "greedy killer"
    '~Your user ID is: (\d+)~',
    '~Your activation ID is: (\d+)~')

if( !preg_match( $regexs[0], $text, $match)){
    throw new Exception('Invalid mail format, cannot find user name');
}

// .. and so on for each field

但是,您可以将所有内容放入一个正则表达式中(如果您使用named subpattern,则可读性会更好:

$regexp = '~Hi\s+(?P<name>.+?)|Your user ID is: (?P<id>\d+)|Your activation ID is: (?P<activation_id>\d+)~';
$matches = array();
preg_match_all( $regexp, $text, $matches, PREG_SET_ORDER);
foreach( $matches as $match){
    print_r( $match);
    if( !empty( $match['name'])){
       // Having a name
    }
}

【讨论】:

  • 当我var_export($matches)时返回一个空数组
猜你喜欢
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 2021-11-21
  • 2023-03-03
  • 2011-08-03
相关资源
最近更新 更多