【发布时间】:2017-04-06 13:49:45
【问题描述】:
此脚本搜索带有单词的行并打印它们,同时在每次迭代中重新读取源文件:
# 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
请解释一下为什么运行脚本不是无止境。
在正则表达式引擎的每个 while 迭代偏移中应重置,因为表达式已更改(新的 cat 已分叉)。
我认为 perl 对 cat 结果进行了某种缓存,但 strace 声称 cat 被生成了 4 次(3 行 3 行 + 1 错误 while 条件) :
# 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", ["cat", "aa"], [/* 24 vars */] <unfinished ...>
[pid 22606] execve("/bin/cat", ["cat", "aa"], [/* 24 vars */] <unfinished ...>
[pid 22607] execve("/bin/cat", ["cat", "aa"], [/* 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';
}
这两个脚本的区别在哪里?我错过了什么?
【问题讨论】:
-
这是个好问题
-
对于那些没有 strace 的用户,您可以使用例如这个 bash 脚本
mycat作为for i in aa bb cc; do echo "${i}_$BASHPID"; done(ofcchmod 755 mycat)。它会为每个循环显示不同的$BASH_PID。 :) -
也许反引号正在重用相同的内存缓冲区,这使 /g 误以为它是同一个字符串。
-
qx反击。第 V 集 - 为什么不使用反引号... :)