我有这个代码来处理配置文件:
<?php
$config = '[log]
log_writers[] = "file"
log_writers[] = "screen"
[General]
maintenance_mode = 0
enable_browser_archiving_triggering = 0
enable_sql_optimize_queries = 0
force_ssl = 1';
echo preg_match_all( '/^maintenance_mode[ \t]*=[ \t]*\d$/m', $config );
回波显示
0
将正则表达式更新为:
echo preg_match_all( '/^maintenance_mode[ \t]*=[ \t]*\d\s$/m', $config );
达到预期效果
1
为什么??
我什至在 regex101 中验证了我的理智
https://regex101.com/r/CIxCkN/1
本地测试环境:
RHEL 7
PHP 5.6.25
PCRE v8.32 2012-11-30
和
Windows Server 2022
PHP 8.2.7
PCRE v10.40 2022-04-14
一个答案是您的字符串(或通常的脚本)具有 Windows 行结尾。
在多行模式下,
\d$
仅匹配数字后跟一个立即换行符(由PCRE的编译时设置确定),如果其中隐藏了\r
,则可能无法工作。
在正则表达式末尾添加
\s
将匹配所有行结束字符,这解释了为什么这对受影响的测试环境有帮助。
对于修复(除了您已经找到的
\s
添加之外),PCRE 允许您使用字符串开头的修饰符来调整哪些字符匹配为换行符,例如(*ANYCRLF)
:
// Force Windows line-ending
<?php
$test = "foo\r\nbar";
var_dump(preg_match_all('/^foo$/m', $test));
var_dump(preg_match_all('/(*ANYCRLF)^foo$/m', $test));
int(0)
整数(1)
请参阅 https://3v4l.org/vOUgM 进行演示,并参阅 PCRE 文档的 换行约定部分了解一些详细信息。
或者,只需在字符串中使用 PCRE 在本地期望的换行符。