使用preg_match_all将所有数字与正则表达式匹配

时间:2017-02-07 16:57:54

标签: php regex preg-match-all

我有一个文字,并尝试在其中添加每个3号码的链接 我使用带有模式的preg_match_all:(^|[^\d])(\d{3})($|[^\d])
此处使用分组仅将链接添加到数字,而不是添加到其邻居。 测试用例是:

  1. a 123 234 b - 必须匹配123和234
  2. a 123_234 b - 必须匹配123和234
  3. aa123 234 b - 必须匹配123和234
  4. a0123 234 b - 必须匹配 234
  5. 123a234 b - 必须匹配123和234
  6. a 123 234 - 必须匹配123和234
  7. 测试2和3工作正常,其他测试因两个数字之间的空间而失败 如何匹配两个数字之间只有1个空格?

2 个答案:

答案 0 :(得分:4)

您可以通过使用正向前瞻 - api doc替换最后一个捕获组来“修复”您的正则表达式,以允许重叠匹配。 {3}组之后($|[^\d])组消耗了空格,而第一个(^|[^\d])无法与该空格匹配。如果您更喜欢这种方法,我会用[^\d]替换\D

我建议使用负面外观,因为它看起来“更干净”:

(?<!\d)\d{3}(?!\d)
^^^^^^      ^^^^^^

请参阅(^|[^\d])(\d{3})(?=$|[^\d])

<强>详情:

  • (?<!\d) - 当前位置不应以数字
  • 开头
  • \d{3} - 3位数
  • (?!\d) - 当前位置右侧必须没有数字。

答案 1 :(得分:1)

这是我的两分钱:

\d{4,}(*SKIP)(*FAIL)|(\d{3})

正则表达式示例为here

这意味着:

\d{4,}(*SKIP)(*FAIL)  -> match 4 digits or more but skip the match
|                     -> Or
(\d{3})               -> match 3 digits and capture it. 

这意味着您的正则表达式仅匹配捕获组中3位数的出现次数。

希望它有所帮助。

编辑

添加了(*SKIP)(*FAIL)个动词。

这两个动词允许您强制匹配失败。然后,可以完成替换。 (参见regex101示例的替换部分)。

在php中,代码如下所示:

$arr = array(
    "a 123 234 b",
    "a 123_234 b",
    "aa123 234 b",
    "a0123 234 b",
    "123a234 b",
    "a 123 234"
);

$regex = "/\d{4,}(*SKIP)(*FAIL)|(\d{3})/";

foreach ($arr as $item) {
    echo preg_replace($regex, '<a href="#">$1</a>', $item);
    echo "\r\n";
}

输出:

a <a href="#">123</a> <a href="#">234</a> b
a <a href="#">123</a>_<a href="#">234</a> b
aa<a href="#">123</a> <a href="#">234</a> b
a0123 <a href="#">234</a> b
<a href="#">123</a>a<a href="#">234</a> b
a <a href="#">123</a> <a href="#">234</a>