使用 preg_match_all 将所有数字与正则表达式匹配
Posted
技术标签:
【中文标题】使用 preg_match_all 将所有数字与正则表达式匹配【英文标题】:Matching all numbers with regex using preg_match_all 【发布时间】:2017-06-25 00:57:18 【问题描述】:我有一个文本,并尝试将链接添加到其中的每个大小为 3 的数字。
我将 preg_match_all 与一个模式一起使用:(^|[^\d])(\d3)($|[^\d])
此处使用分组来仅将链接添加到数字,而不是添加到它们的邻居。
测试用例是:
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 工作正常,其他测试因 2 个数字之间的空格而失败。 如何匹配两个数字之间只有 1 个空格?
【问题讨论】:
另外,您可以“修复”您的正则表达式,只需将最后一个捕获组替换为正向前瞻(^|[^\d])(\d3)(?=$|[^\d])
,以允许重叠匹配。我建议使用环视,因为这样看起来“更干净”。见regex101.com/r/27pWL2/1。 Surley,如果您更喜欢这种方法,我会将 [^\d]
替换为 \D
。
【参考方案1】:
这是我的两分钱:
\d4,(*SKIP)(*FAIL)|(\d3)
正则表达式示例是here。
意思是:
\d4,(*SKIP)(*FAIL) -> match 4 digits or more but skip the match
| -> Or
(\d3) -> 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 = "/\d4,(*SKIP)(*FAIL)|(\d3)/";
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>
【讨论】:
【参考方案2】:您可以“修复”您的正则表达式,只需将最后一个捕获组替换为 正向预测 - (^|[^\d])(\d3)(?=$|[^\d])
- 以允许重叠匹配。 ($|[^\d])
组消耗了 3 位块之后的空间,第一个 (^|[^\d])
无法匹配该空间。 Surley,如果您更喜欢这种方法,我会将[^\d]
替换为\D
。
我建议使用负面的环视,因为这样看起来“更干净”:
(?<!\d)\d3(?!\d)
^^^^^^ ^^^^^^
见regex demo
详情:
(?<!\d)
- 当前位置不应以数字开头
\d3
- 3 位数
(?!\d)
- 当前位置右侧不能有数字。
【讨论】:
如果您需要替换preg_replace
中的匹配项,请使用 $0
反向引用替换整个匹配项。
非常感谢!你的建议更清晰,更容易理解。以上是关于使用 preg_match_all 将所有数字与正则表达式匹配的主要内容,如果未能解决你的问题,请参考以下文章