Eu tenho este código para processar um arquivo de configuração:
<?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 );
O eco exibe0
Atualizando o regex para:
echo preg_match_all( '/^maintenance_mode[ \t]*=[ \t]*\d\s$/m', $config );
resultados no esperado1
POR QUE??
Eu até verifiquei minha sanidade no regex101
https://regex101.com/r/CIxCkN/1
Ambientes de teste locais:
RHEL 7
PHP 5.6.25
PCRE v8.32 30/11/2012
e
Windows Server 2022
PHP 8.2.7
PCRE v10.40 14/04/2022
Por solicitação de comentário:
var_dump(base64_encode($config));
string (240) "W2xvZ10NCmxvZ193cml0ZXJzW10gPSAiZmlsZSINCmxvZ193cml0ZXJzW10gPSAic2NyZWVuIg0KDQpbR2VuZXJhbF0NCm1haW50ZW5hbmNlX21vZGUgPSAwDQplbmFibG VfYnJvd3Nlcl9hcmNoaXZpbmdfdHJpZ2dlcmluZyA9IDANCmVuYWJsZV9zcWxfb3B0aW1pemVfcXVlcmllcyA9IDANCmZvcmNlX3NzbCA9IDE="
var_dump(bin2hex($config));
string (358) "5b6c6f675d0d0a6c6f675f777269746572735b5d203d202266696c65220d0a6c6f675f777269746572735b5d203d202273637265656e220d0a0 d0a5b47656e6572616c5d0d0a6d61696e74656e616e63655f6d6f6465203d20300d0a656e61626c655f62726f777365725f617263686976696e675f7472 6967676572696e67203d20300d0a656e61626c655f73716c5f6f7074696d697a655f71756572696573203d20300d0a666f7263655f73736c203d2031"
Uma resposta seria que sua string (ou script em geral) possui finais de linha do Windows.
No modo multilinha,
\d$
corresponderá apenas a um dígito seguido por uma nova linha imediata (conforme determinado pela configuração de tempo de compilação do PCRE), o que pode não funcionar se houver algo\r
oculto ali.Adicionar
\s
no final do seu regex corresponderia a todos os caracteres de final de linha, o que explica por que isso ajuda nos ambientes de teste afetados.Para uma correção (além da
\s
adição que você já encontrou), o PCRE permite ajustar quais caracteres são correspondidos como uma nova linha usando um modificador no início da string, por exemplo(*ANYCRLF)
:Consulte https://3v4l.org/vOUgM para obter uma demonstração e a seção Newline Conventions dos documentos PCRE para obter mais detalhes.
Ou, alternativamente, apenas use os caracteres de nova linha em sua string que o PCRE espera localmente.
E de maneira mais geral, se você estiver realmente tentando analisar a string/arquivo em sua pergunta, uma combinação de
array_key_exists
eparse_ini_string/parse_ini_file
tornará tudo muito mais limpo.