open ( F1, "file1.txt" );
open ( F2, "+>file2.txt" );
$/ = "\n\n" ;
while (<F1>) {
print F2;
$/ = "\n" ;
@arr = <F2> ;
@found = grep(/^: /, @arr);
if( $#found == -1) {
truncate(F2, $length);
}
$/ = "\n\n" ;
}
请帮我在此代码中找到错误。
FILE1.TXT:
:a
:b
: x
:y
注意::a,:b和:x,:y用“\ n”分隔,并且:b和:x用“\ n \ n”分隔
执行程序后file2.txt中的预期内容:
: x
:y
答案 0 :(得分:5)
您的程序有问题,但很难说出您可能指的是什么,因为您实际上没有指定问题或问题。
open ( F1, "file1.txt" );
open ( F2, "+>file2.txt" );
你应该使用三个参数open,使用显式模式和词法文件句柄。此外,您应该检查open
的返回值,看它没有失败以及原因。此外,为文件句柄使用更好的名称也不会有害。
open my $in, "<", "file1.txt" or die "Cannot open file1.txt for reading: $!";
open my $out, "+>", "file2.txt" or die "Cannot open file2.txt for overwrite: $!";
请注意,文件打开模式+>
会在您打开文件时截断文件,但允许您同时对文件句柄进行读写操作。大多数时候,你不想要这个。
$/ = "\n\n" ;
while (<F1>) {
将输入记录分隔符设置为$/
将读取输入文件中的段落,在您的情况下(假设我的格式正确),这将是
$_ = ":a
:b
";
然后将此值打印到输出文件
print F2; # this means "print F2 $_"
然后再次更改输入记录分隔符,并读取输出文件中的所有行:
$/ = "\n" ;
@arr = <F2> ;
但不幸的是,这是错误的,因为文件句柄的位置将位于文件末尾(eof
),因为这是您正在打印的文件句柄。因此@arr
将为空。
@found = grep(/^: /, @arr);
if( $#found == -1) {
truncate(F2, $length);
}
因此,truncate
的代码将永远发生。当然,$length
是一个未定义的变量,所以它会给你一个警告,例如Use of uninitialized value $length in truncate at ...
,除非你如此愚蠢以至于不使用:
use warnings;
我认为你在这里要做的就是在将输入打印到输出之前检查输入,但你应该知道之后尝试打印和截断是一个可怕的想法。为什么不在打印之前检查它呢?这不仅是99.99%的时间,它也是最简单,最合理的方式。
if (/^: /) {
print $out $_;
}
/^: /
是$_ =~ /^: /
的缩写,如果您不确定 - 它将正则表达式匹配运算符应用于默认输入变量$_
,这是您在while (<F1>)
循环条件,是while ($_ = <F1>)
在你的程序中,你应该总是使用
use strict;
use warnings;
并学会使用它们,因为它们可以在调试时为您节省大量时间,并为您提供有关您的程序正在执行的操作的重要信息。
所以你得到:
use strict;
use warnings;
open my $in, "<", "file1.txt" or die "Cannot open file1.txt for reading: $!";
open my $out, "+>", "file2.txt" or die "Cannot open file2.txt for overwrite: $!";
$/ = "\n\n";
while (<$in>) {
if (/^: /) {
print $out $_;
}
}
请注意,您可以通过简单的单线程序解决此问题
perl -00 -nle 'print if /^: /' file1.txt > file2.txt