PHP中preg_match_all匹配失败,但在线正则测试器可成功
问题分析与解决方案
首先咱们得搞清楚为啥regex101里测试成功,但PHP里却匹配不到——核心问题出在m修饰符的适用场景,以及你测试时和PHP代码里字符串结构的差异上。
问题根源
你在regex101测试时,大概率是把每个|Test|放在了单独的行里(比如每行一个|Test|),这时候/^\|.*\|$/m的^和$在多行模式下会匹配每行的开头和结尾,自然能命中目标。但你的PHP代码里的字符串是一整行的:
$str = 'Why is this not working? |Test| |Test| |Test| |Test| ';
这里所有的|Test|都挤在同一行中,既不在整个字符串的开头(^匹配的是Why的位置),也不在整个字符串的结尾($匹配的是最后的空格位置),加了m修饰符也没用——因为整个字符串里没有换行,m修饰符根本没机会发挥作用。
两种解决方案(根据你的实际需求选择)
1. 如果你确实想匹配「单独一行的|开头|结尾内容」
那需要让目标内容处于单独的行中,也就是给字符串加上换行符,比如:
$re = '/^\|.*\|$/m'; $str = "Why is this not working?\n|Test|\n|Test|\n|Test|\n|Test| "; preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0); var_dump($matches);
这时候m修饰符会生效,^匹配每个换行后的行首,$匹配换行前的行尾,就能匹配到那几行|Test|了。
2. 如果你只是想匹配同一行中「被|包裹的子串」
那完全不需要^、$和m修饰符,直接匹配所有被|包裹的内容即可:
$re = '/\|[^|]*\|/'; // [^|]* 匹配任意非|的字符,避免错误匹配跨多个|的内容 $str = 'Why is this not working? |Test| |Test| |Test| |Test| '; preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0); var_dump($matches);
这个正则会匹配所有像|Test|这样的子串,不管它们在一行的哪个位置。
补充:PHP中m修饰符的作用
再啰嗦一句,m修饰符的本质是改变^和$的匹配范围:
- 默认模式:
^匹配整个字符串的开头,$匹配整个字符串的结尾 - 多行模式(加
m):^匹配每行的开头(即\n之后的位置),$匹配每行的结尾(即\n之前的位置)
只有当字符串里包含换行符时,m修饰符才会有实际效果哦。
内容的提问来源于stack exchange,提问作者user2774183
相关产品推荐
相关产品推荐

