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

Matching all numbers with regex using preg_match_all

我有一个文本,并尝试将 link 添加到其中的每个 3 号数字。
我将 preg_match_all 与模式一起使用:(^|[^\d])(\d{3})($|[^\d])
这里使用分组来仅将 link 添加到数字,而不是它们的邻居。 测试用例是:

  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

测试 2 和 3 工作正常,其他测试失败,因为 space 介于 2 个数字之间。
如何匹配两个数字之间只有 1 space?

您可以 "fix" 您的正则表达式,只需将最后一个捕获组替换为 正向先行 - (^|[^\d])(\d{3})(?=$|[^\d]) - 以允许重叠匹配。 ($|[^\d]) 组消耗了 3 位数字块后的 space,第一个 (^|[^\d]) 无法匹配 space。 Surley,如果您更喜欢这种方法,我会将 [^\d] 替换为 \D

我建议使用负面环视,因为它看起来像 "cleaner":

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

regex demo

详情:

  • (?<!\d) - 当前位置前面不应有数字
  • \d{3} - 3 位数
  • (?!\d) - 当前位置右边不能有数字。

这是我的两分钱:

\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="#"></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>