使用 preg_match_all 将所有数字与正则表达式匹配
Matching all numbers with regex using preg_match_all
我有一个文本,并尝试将 link 添加到其中的每个 3 号数字。
我将 preg_match_all 与模式一起使用:(^|[^\d])(\d{3})($|[^\d])
这里使用分组来仅将 link 添加到数字,而不是它们的邻居。
测试用例是:
a 123 234 b
- 必须匹配 123 和 234
a 123_234 b
- 必须匹配 123 和 234
aa123 234 b
- 必须匹配 123 和 234
a0123 234 b
- 必须匹配 仅 234
123a234 b
- 必须匹配 123 和 234
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)
^^^^^^ ^^^^^^
详情:
(?<!\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>
我有一个文本,并尝试将 link 添加到其中的每个 3 号数字。
我将 preg_match_all 与模式一起使用:(^|[^\d])(\d{3})($|[^\d])
这里使用分组来仅将 link 添加到数字,而不是它们的邻居。
测试用例是:
a 123 234 b
- 必须匹配 123 和 234a 123_234 b
- 必须匹配 123 和 234aa123 234 b
- 必须匹配 123 和 234a0123 234 b
- 必须匹配 仅 234123a234 b
- 必须匹配 123 和 234a 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)
^^^^^^ ^^^^^^
详情:
(?<!\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>