为什么以下 perl 代码:
for(open(my $fh, ">>", "test.txt")){
print $fh "one\n";
}
for(open(my $fh, ">>", "test.txt")){
print $fh "two\n";
}
for(open(my $fh, ">>", "test.txt")){
print $fh "three\n";
}
Run Code Online (Sandbox Code Playgroud)
将以下内容写入 test.txt?
three
two
one
Run Code Online (Sandbox Code Playgroud)
为什么顺序颠倒了?我的理解是每个for
块会在块退出时自动关闭文件。这不应该导致 perl 在下一个块开始之前刷新任何缓冲区吗?我希望这段代码可以打开文件,写一行,关闭文件,然后再重复所有这些步骤两次。我错过了什么?
我用 Perl 5.26.1 测试了这个,在 Ubuntu 18.04.3 上运行。
(是的,我知道只需将所有print
语句放在同一个块中,我就可以轻松地以正确的顺序编写行。这不是这里的问题。我想了解为什么会发生这种行为。)
对于奖励奇怪,当我运行以下代码时:
for my $val (qw/ one two three /) {
for(open(my $fh, ">>", "test.txt")){
print $fh "$val\n";
}
}
Run Code Online (Sandbox Code Playgroud)
它给了我以下输出:
one
two
three
Run Code Online (Sandbox Code Playgroud)
这段代码看起来应该与之前的代码在功能上相同。为什么它的行为不同?
这只是一个复杂的版本
open(my $fh, ">>", "test.txt");
print $fh "one\n";
open(my $fh, ">>", "test.txt");
print $fh "two\n";
open(my $fh, ">>", "test.txt");
print $fh "three\n";
Run Code Online (Sandbox Code Playgroud)
让我们做些小改动,让事情更易读,更容易讨论:
open(my $fh1, ">>", "test.txt");
print $fh1 "one\n";
open(my $fh2, ">>", "test.txt");
print $fh2 "two\n";
open(my $fh3, ">>", "test.txt");
print $fh3 "three\n";
Run Code Online (Sandbox Code Playgroud)
这是等效的,因为每个都my
创建了一个新变量。
那么发生了什么?
open(my $fh1, ">>", "test.txt"); # You create a file handle.
print $fh1 "one\n"; # You write to the file handle's buffer.
open(my $fh2, ">>", "test.txt"); # You create a file handle.
print $fh2 "two\n"; # You write to the file handle's buffer.
open(my $fh3, ">>", "test.txt"); # You create a file handle.
print $fh3 "three\n"; # You write to the file handle's buffer.
# Implicit close($fh3); # You close the file handle, flushing its buffer.
# Implicit close($fh2); # You close the file handle, flushing its buffer.
# Implicit close($fh1); # You close the file handle, flushing its buffer.
Run Code Online (Sandbox Code Playgroud)
由于 Perl 不保证销毁变量的顺序,因此您可以轻松地以任何顺序获得输出。
解决方案是在打印到手柄后冲洗它们($fh->flush;
、 或$fh->autoflush(1);
),或者提前关闭手柄。
{ open(my $fh, ">>", "test.txt"); print $fh "one\n"; }
{ open(my $fh, ">>", "test.txt"); print $fh "two\n"; }
{ open(my $fh, ">>", "test.txt"); print $fh "three\n"; }
Run Code Online (Sandbox Code Playgroud)