首页 > 解决方案 > 在 Perl 中逐行读取文件

问题描述

我想逐行读取文件,但它只读取第一行。如何阅读所有行?

我的代码:

open(file_E, $file_E);

while ( <file_E> ) {
    /([^\n]*)/;
    print $line1;
}

close($file_E);

标签: perllinereadfile

解决方案


让我们从查看您的代码开始。

open(file_E, $file_E);

while ( <file_E> ) {
    /([^\n]*)/;
    print $line1;
}

close($file_E);

$file_E在第一行,您使用裸字文件句柄打开一个名为 in的文件file_E。只要文件成功打开,这应该可以工作。最好也通过以下两种方法之一检查此操作的成功:要么放在use autodie;脚本的顶部(但随后冒险将其语义应用到代码与此级别错误处理不兼容的地方),或者更改您的open看起来像这样:

open(file_E, $file_E) or die "Failed to open $file_E: $!\n";

现在,如果您无法打开该文件,您将收到一条错误消息,有助于追查问题。

接下来让我们看一下while循环,因为在这里您遇到了导致您遇到的错误的问题。在while循环的第一行你有这个:

while ( <file_E> ) {

通过咨询perldoc perlsyn,您会看到该行是实际执行此操作的特殊情况:

while (defined($_ = <file_E>)) {

因此,您的代码隐式地将每一行分配给$_连续迭代。此外,通过咨询perldoc perlop您会发现,当调用匹配运算符 ( /.../or ) 时未使用 显式绑定匹配,匹配将绑定到. 尽管如此,到目前为止还不错。但是,您实际上并没有对比赛做任何有用的事情。匹配运算符将返回布尔真/假以判断匹配是否成功。而且因为您的模式包含捕获括号,它会将某些内容捕获到捕获变量中。但是您永远不会测试匹配成功,也不会再次提及。m/.../=~$_$1$1

在接下来的行中,您执行以下操作:print $line1. 在您的代码中,在哪里$line1被分配了一个值?因为它从来没有被赋予你向我们展示的价值。

我只能猜测您的意图是遍历文件的行,捕获该行但没有尾随换行符,然后打印它。似乎您希望打印它而不使用任何换行符,以便将所有输入文件打印为单行输出。

open my $input_fh_e, '<', $file_E or die "Failed to open $file_E: $!\n";

while(my $line = <$input_fh_e>) {
    chomp $line;
    print $line;
}

close $input_fh_e or die "Failed to close $file_E: $!\n";

无需捕获任何东西——如果捕获所做的只是将所有内容抓取到换行符之前,您可以简单地从换行符chomp开始剥离。

在我的示例中,我使用了一个词法文件句柄(一个词法范围的文件句柄,用 声明my)。这在现代 Perl 中通常是一种更好的做法,因为它避免使用裸字,避免可能的命名空间冲突,并确保一旦词法范围关闭,句柄就会关闭。

我还使用了 '三 arg' 版本open,它更安全,因为它消除了$file_E用于打开管道或进行其他一些邪恶或只是无意的 shell 操作的可能性。

我建议也用 开始你的脚本use strict;,因为如果你这样做了,你会在编译时收到一条错误消息,告诉你$line1从未声明过。还要以 开始您的脚本,以便在为它分配值之前use warnings尝试打印时会收到警告。$line1

代码中的大部分问题将在 中进行讨论,假设您安装了 Perl,perldoc perlintro您可以通过简单地从命令行输入 来解决这些问题。perldoc perlintro通读通常需要 20-40 分钟perlintro。如果在开始编写 Perl 代码之前有一个文档应该构成必需阅读,那么该阅读可能包括perlintro.


推荐阅读