端线锚点,$,行为不符合预期

问题描述 投票:0回答:2

我有这个代码来处理 Windows 中的配置文件:

<?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

https://onlinephp.io/c/51407

将正则表达式更新为:

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


每个评论请求:

var_dump(base64_encode($config));

字符串(240)“W2xvZ10NCmxvZ193cml0ZXJzW10gPSAiZmlsZSINCmxvZ193cml0ZXJzW10gPSAic2NyZWVuIg0KDQpbR2VuZXJhbF0NCm1haW50ZW5hbmNlX21vZGUgPSAwDQplbmFib GVfYnJvd3Nlcl9hcmNoaXZpbmdfdHJpZ2dlcmluZyA9IDANCmVuYWJsZV9zcWxfb3B0aW1pemVfcXVlcmllcyA9IDANCmZvcmNlX3NzbCA9IDE="

var_dump(bin2hex($config));

字符串(358)“5b6c6f675d0d0a6c6f675f777269746572735b5d203d202266696c65220d0a6c6f675f777269746572735b5d203d202273637265656e220 d0a0d0a5b47656e6572616c5d0d0a6d61696e74656e616e63655f6d6f6465203d20300d0a656e61626c655f62726f777365725f617263686976696e675f 74726967676572696e67203d20300d0a656e61626c655f73716c5f6f7074696d697a655f71756572696573203d20300d0a666f7263655f73736c203d203 1"

php regex anchor preg-match-all
2个回答
4
投票

一个答案是您的字符串(或通常的脚本)具有 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 在本地期望的换行符。


更一般地说,如果您实际上正在尝试解析问题中的字符串/文件,那么

array_key_exists
parse_ini_string/parse_ini_file
的组合将使一切变得更加清晰。


0
投票

你的配置文件确实有windows-newlines

\r\n
,你的bin2hex
5b6c6f675d0d0a
的第一部分翻译成
[log]\r\n
,这意味着@iainn的预感是正确的:)

尽管如此,我还是会把正则表达式写成

'/^维护模式\s*=\s*(\d)\s*$/m'

这样会更健壮,所以写成这样也没关系

maintenance_mode=5

maintenance_mode =5

maintenance_mode= 5

maintenance_mode = 5

,无论您使用空格还是制表符,也无论您的行结尾是什么。

© www.soinside.com 2019 - 2024. All rights reserved.