【问题标题】:Reading a file line by line in Perl在 Perl 中逐行读取文件
【发布时间】:2018-04-30 12:49:22
【问题描述】:

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

我的代码:

open(file_E, $file_E);

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

close($file_E);

【问题讨论】:

  • Perl read line by line的可能重复
  • 那里的正则表达式的目的是什么?什么是$line1,它从哪里获得价值?你的缩进怎么了?
  • while(&lt;file_E&gt;) 会将每一行读入$_,但您正在打印$line1。我建议您use warnings; use strict; 并检查open 是否有错误。请阅读perlintro - 它会向您展示您需要的基础知识。
  • 正在读取所有行;你只是没有对他们做任何事情。

标签: perl line readfile


【解决方案1】:

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

open(file_E, $file_E);

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

close($file_E);

在第一行,您使用裸字文件句柄file_E 打开一个名为$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,您会发现当调用匹配运算符(/.../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 中通常是一种更好的做法,因为它避免使用裸字,避免可能的命名空间冲突,并确保句柄在词法范围关闭时立即关闭。

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

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

您的代码中的大部分问题都将在perldoc perlintro 中进行讨论,假设您安装了 Perl,您只需键入 perldoc perlintro 从命令行即可到达。通读perlintro 通常需要 20-40 分钟。如果在开始编写 Perl 代码之前有一个文档应该构成必读,那么该阅读可能包括perlintro

【讨论】:

  • 使用两个参数 open 是个坏主意。更好:open my $input_fh_e, "&lt;", $file_E or die ...
  • 感谢@melpomene,不知道我是如何允许自己打开 2-arg 的。固定。
【解决方案2】:

另一种选择,请注意 $_ 将包含换行符,因此如果您不想在 $line 中使用换行符,则需要将其剔除:

open(file_E, $file_E);

while ( <file_E> ) {
    my $line = $_;
    print $line;
}

close($file_E);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2013-12-26
    • 2015-05-12
    • 2022-01-25
    • 2014-04-04
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多