Perl 文件句柄 - 覆盖现有数据而不是 appending/deleting

Perl file handles - overwrite existing data instead of appending/deleting

cat -E test1.txt

输出:

car$
$
$

我只想将 "car" 更改为 "bike" 并删除 new/empty 行。

这按预期工作:

#!/usr/bin/perl -w
open(FILE1,"<","./test1.txt"); @araj=<FILE1>; close(FILE1);
open(FILE2,">","./test1.txt");
map {
s@car@bike@; s@^\n@@;
} @araj;
print(FILE2 @araj);
close(FILE2);

cat -E test1.txt

输出对我来说是 100% 正确的:

bike$

但在上述情况下,我使用的是 2x opening/close 文件。 所以我正在使用 2x 文件句柄。
我只想使用 1x 文件句柄
(出于学习目的,只是想了解 +> +>> >> 是如何工作的...)。
例如:

#!/usr/bin/perl -w
open(FILE2,"+<","./test1.txt"); #what file handle should be here? +> , +>> >> .... ?
@araj=<FILE2>;
map {
s@car@bike@; s@^\n@@;
} @araj;
print(FILE2 @araj);
close(FILE2);

输出不正确:

car$
$
$
bike$

为什么这是追加,而不是覆盖?当我使用其他文件句柄时,结果也不正确,例如空文件... 哪个文件句柄用于读取和覆盖?

Why this is appending, but no overwriting?

您首先读取了所有数据,直到文件末尾。这意味着下一次读取或写入的文件位置现在在您已读取的所有数据之后,即在文件末尾。如果要从文件开头写入数据,则需要使用 seek:

更改文件位置
 seek($filehandle,0,0); # position at beginning of file

您写入的下一个数据将从这个新的文件位置开始写入,即从文件的开头开始。完成后,您可能需要使用 truncate with the current file position you've got with tell:

从文件中删除当前文件位置之后的所有数据
 truncate($filehandle, tell($filehandle));

或者,整个程序:

use strict;
use warnings;
open(my $fh, "+<", "./test1.txt");
my @araj = <$fh>;
for(@araj) {
    s{car}{bike};
    s{^\n}{};
}
seek($fh, 0, 0);           # seek at the beginning of the file
print $fh @araj;
truncate($fh, tell($fh));  # remove everything after current file position
close($fh);

读取数组中的文件后,文件句柄位置是文件末尾。 然后你应该通过 seek 函数(在文件开头设置)perldoc seek 更改文件句柄位置。 接下来按 truncate perldoc truncate

调整文件大小
#!/usr/bin/perl -w
open(FILE2,"+<","./test1.txt"); #what file handle should be here? +> , +>> >> .... ?
@araj=<FILE2>;
map {
s@car@bike@; s@^\n@@;
} @araj;

seek(FILE2, 0, 0);
print(FILE2 @araj);
truncate(FILE2, tell(FILE2));

close(FILE2);