此脚本将搜索具有单词并打印它们的行,同时在每次迭代中重新读取源文件:
# cat mm.pl #!/usr/bin/perl use strict; use warnings; while( `cat aa` =~ /(\w+)/g ) { print "$1\n"; }
输入文件:
# cat aa aa bb cc
结果:
# ./mm.pl aa bb cc
请解释我为什么运行脚本不是无止境的.
由于表达式发生变化(新的猫被分叉),所以每次正则表达式引擎的迭代偏移都应该被重置.
我认为perl对猫的结果做了某种缓存,但是strace声称猫被产生了4次(3条为3条1,而条件为假):
# strace -f ./mm.pl 2>&1 | grep cat | grep -v ENOENT [pid 22604] execve("/bin/cat",["cat","aa"],[/* 24 vars */] <unfinished ...> [pid 22605] execve("/bin/cat",[/* 24 vars */] <unfinished ...> [pid 22606] execve("/bin/cat",[/* 24 vars */] <unfinished ...> [pid 22607] execve("/bin/cat",[/* 24 vars */] <unfinished ...>
另一方面,以下示例永远运行:
# cat kk.pl #!/usr/bin/perl use strict; use warnings; my $d = 'aaa'; while( $d =~ /(\w+)/g ) { print "$1\n"; $d = 'aaa'; }
两个脚本之间的区别在哪里?我失踪了什么
// g离开的位置存储在魔术中,添加到执行匹配的标量中.
原文链接:https://www.f2er.com/regex/357133.html$perl -MDevel::Peek -e'$_ = "abc"; Dump($_); /./g; Dump($_);' SV = PV(0x32169a0) at 0x3253ee0 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x323bae0 "abc"\0 CUR = 3 LEN = 10 COW_REFCNT = 1 SV = PVMG(0x326c040) at 0x3253ee0 REFCNT = 1 FLAGS = (SMG,POK,pPOK) IV = 0 NV = 0 PV = 0x323bae0 "abc"\0 CUR = 3 LEN = 10 COW_REFCNT = 2 MAGIC = 0x323d050 MG_VIRTUAL = &PL_vtbl_mglob MG_TYPE = PERL_MAGIC_regex_global(g) MG_FLAGS = 0x40 BYTES MG_LEN = 1
这意味着在反引号中观察到的行为的唯一方法是示例,如果匹配运算符匹配相同的标量,则四次被评估!怎么可能?这是因为反引号是使用TARG的运算符之一.
创建标量是相对昂贵的,因为它需要最多三个内存分配!为了提高性能,称为TARG的标量与一些运算符的每个实例相关联.当对具有TARG的运算符进行评估时,它可以使用返回的值填充TARG并返回TARG(而不是分配并返回新的值).
“那么什么?”,你可能会问.毕竟,您已经表明,分配到标量将重置与该标量相关联的匹配位置.这是假设发生的,但它不适用于反引号.
魔术不仅允许将信息附加到变量,它还附加在特定条件下被调用的功能.由gg添加的魔法附加了一个在标量被修改之后应该调用的函数(由上面的转储中的SMG标志指示).当将值分配给标量时,此功能将清除位置.
赋值运算符正确处理魔术,但不能由反驳操作符处理.它并不期望魔法被添加到它的TARG,所以它不检查是否有任何,所以清除匹配位置的功能是不必要的.