regex - 从 `^` 中删除 `s/^/1/;` 会导致我的代码失败。为什么?

标签 regex perl

我一直在研究 this problem在代码高尔夫交换中,这就是为什么我的代码看起来如此有趣。

这是一个使用 use strictuse warnings 重现问题的程序:

use strict;
use warnings;

$_ = "";

for my $i (1..33){
    s//1/;   # Just prepends 1 to the string $_
}
print "$_\n";

for my $i (34..127) {
    if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
        print chr y/1/1/;
    }
    s/^/1/;   # Prepends 1 to the start of the string.
}

这是输出:

111111111111111111111111111111111
#$%&04689@ABDOPQRabdegopq

这正如我所期望的那样。但是,当我从第二个正则表达式中取出 ^ 时,正则表达式不再匹配并延长字符串。

use strict;
use warnings;

$_ = "";

for my $i (1..33){
    s//1/;
}
print "$_\n";

for my $i (34..127) {
    if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
        print chr y/1/1/;
    }
    s//1/;   # No Longer matches!
}

为什么会发生这种情况? s//1/ 在第一个循环中有效,那么为什么在第二个循环中更改它会破坏一切呢?

还有一个令人困惑的地方,如果将 if block 放在大括号中,则正则表达式会再次匹配:

for my $i (34..127) {
    {
        if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
            print chr y/1/1/;
        }
    }
    s//1/;   # This prepends 1 to the string $_ again.
}

编辑:

我想将原始代码编辑回到问题中以供引用:

use strict;
use warnings;
$_="";
until( y/1/1/ > 32){
    print "test1";
    s//1/;
    print "test";
}
print "$_\n";
until( y/1/1/ > 125+1 ) {
    if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
        print chr y/1/1/;
    }

    s/^/1/; # this is the line we remove ^ from
}

当我们从该行中删除 ^ 时,输出将更改为:

test1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1test111111111111111111111111111111111
#$%&04689@ABDOPQRabdegopq

hanging with no output

因此,在这种情况下,第二个循环中的行更改似乎改变了第一个循环的行为。

最佳答案

s//1/; 不检查任何字符串或空字符串。它会检查之前最后一次成功的正则表达式文本。因此,第一个循环使用默认正则表达式,第二个循环使用上面 if 中最后一次成功的检查。

引用:

If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead. In this case, only the g and c flags on the empty pattern are honored

请参阅The empty pattern //

关于regex - 从 `^` 中删除 `s/^/1/;` 会导致我的代码失败。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25026656/

相关文章:

java - 带有特殊字符和空格的正则表达式模式问题

javascript - 可选组在正则表达式中不起作用

c# - 基于严格要求的正则表达式拆分和提取

C#正则表达式匹配字符串

perl - 如何使用 Perl 通过套接字发送逐字请求?

用源代码中的值替换变量的 C 编程工具

linux - 我如何检测 Perl 中的符号链接(symbolic link)已损坏?

javascript - 查找具有特定内容的 DIV 标签

perl - 是否可以在 Perl 中保留哈希表的大小?

c# - 正则表达式提取括号之间还包含其他括号的字符串