为什么这个Perl程序没有给出预期的输出?

时间:2013-12-05 05:39:43

标签: perl

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

1 个答案:

答案 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