,php,regex,parsing"/>

首页 > 解决方案 > PHP:preg_match 用于“一些多个单词字符串”+ [\s* +”"]

问题描述

需要以下列可能形式出现的解析字符串:

Some User Name 
Some User Name <user.mail@address>

因此用户名(多个单词)始终存在,但电子邮件是可选的,并且包含在尖括号中。

我需要从那些中抓住:

  1. 用户名,一个字符串,多个单词用\s或\h分隔
  2. 在不带尖括号的下一个电子邮件地址(如果存在)之后。如果未指定电子邮件地址,则生成的子掩码数组应为空(但始终存在于结果中)。

我尝试了一些变化

preg_match('/^(.*?)\s*(?:\<(.*)\>)?$/s', $in, $out)

但这不起作用。

谢谢有人帮助我。

标签: phpregexparsing

解决方案


要获取由可选电子邮件地址分隔的所有单独单词\h,您可以使用\G锚来获取迭代匹配,在上一个匹配结束时断言位置。

(?|^(\w+)|\G(?!^)\h+(\w+))(?:\h+<([^<>\r\n]+)>$)?

解释

  • (?| 分支重置组(保留单词$matches[1]
    • ^(\w+)字符串开头,匹配第 1组中的 1+ 个单词字符
    • |或者
    • \G(?!^)在上一场比赛结束时断言位置,而不是在开始时
    • \h+(\w+)匹配组 1中的 1+ 个水平空白字符
  • )关闭分支重置组
  • (?:非捕获组
    • \h+匹配 1+ 个水平空白字符
    • <([^<>\r\n]+)>$<>在字符串末尾捕获第2 组中的电子邮件地址
  • )?关闭非捕获组并使其可选

正则表达式演示| php演示


使用preg_match_all获取所有值。

默认标志是PREG_PATTERN_ORDER

排序结果,使得 $matches[0] 是一个完整模式匹配的数组,$matches[1] 是一个由第一个带括号的子模式匹配的字符串数组,依此类推。

文字在$matches[1],电子邮件在$matches2

如果电子邮件不存在,则数组将存在,但为空。

您可以使用array_filter从电子邮件数组中删除空条目。

Example code

$pattern = "~(?|^(\w+)|\G(?!^)\h+(\w+))(?:\h+<([^<>\r\n]+)>$)?~";
$strings = [
    "Some User Name ",
    "Some User Name <user.mail@address>"
];

foreach ($strings as $str) {
    preg_match_all($pattern, $str, $matches);
    print_r($matches[1]);
    print_r(array_filter($matches[2]));
}

输出

Array
(
    [0] => Some
    [1] => User
    [2] => Name
)
Array
(
)
Array
(
    [0] => Some
    [1] => User
    [2] => Name
)
Array
(
    [2] => user.mail@address
)

推荐阅读