Mas*_*iti 3 regex perl side-effects
我们最近在一个Perl脚本中遇到了一些奇怪的结果,其中NULL字符(Perl中的\ 0)被引入到某些文本中.我们最终将其跟踪到偶然用于Perl m //匹配运算符的// g运算符.直到发生这种情况,我甚至都不知道你可以使用// g和m //运算符,因为我只使用它与s ///运算符.
无论如何,即使我们通过删除错误// g来修复错误,我也很想知道为什么这个小脚本在文本中引入了一个NULL字符!:-)
my $text = "01";
if ($text =~ m/(\d+)/g)
{
$text = "A$1";
}
if ($text =~ m/\0/)
{
print "Text contains NULL!\n";
}
Run Code Online (Sandbox Code Playgroud)
阻止NULL出现的细微更改:如果我更改$ text的值(例如,更改为"0"或只是"1"或许多其他组合),则不再引入NULL.如果我将赋值值从"A $ 1"更改为"$ 1",则不再引入NULL.如果我将"A $ 1"分配给完全不同的变量,则不会将NULL引入该变量.如果我在m //匹配期间删除了// g运算符,则不会引入NULL.
Perl大师可以解释一下这种行为吗?我用谷歌搜索找不到任何东西.
if ($text =~ m/(\d+)/g)
Run Code Online (Sandbox Code Playgroud)
是错的.具体来说,表单的代码if (/.../g)是错误的.它在概念上没有任何意义("如果匹配,直到它不匹配"???)并且可以给出不希望的结果.
$_ = "01ab";
if (/(\d+)/g) { say $1; } # 01
if (/(.*)/g) { say $1; } # ab!!!
Run Code Online (Sandbox Code Playgroud)
摆脱"g".
字符串的结尾通常后跟NUL.
$ perl -MDevel::Peek -e'Dump "01"'
SV = PV(0x88b4740) at 0x88d1368
REFCNT = 1
FLAGS = (PADTMP,POK,READONLY,pPOK)
PV = 0x88d52f0 "01"\0
CUR = 2
LEN = 12
Run Code Online (Sandbox Code Playgroud)
您的Perl版本似乎有一个错误,当匹配的起始位置在字符串的末尾时,它与NUL匹配.没有插入NUL.幸运的是,如果你修复了你的错误代码,你就不会受到这个bug的影响.
../perl/Porting/bisect.pl \
--target=miniperl --expect-fail \
--start=v5.13.0 --end=v5.14.0 \
-e'
my $text = "01";
if ($text =~ m/(\d+)/g) { $text = "A$1"; }
exit($text =~ m/\0/ ? 1 : 0);
'
Run Code Online (Sandbox Code Playgroud)
显示它由6f1401dc2acd2a2b85df22b0a74e5f7e6e0a33aa修复.
基于git tag --contains 6f1401dc2acd2a2b85df22b0a74e5f7e6e0a33aa5.13.2是第一个开发版本,5.14.0是第一个有修复版本的生产版本.
| 归档时间: |
|
| 查看次数: |
584 次 |
| 最近记录: |