简体   繁体   English

在Perl中读取和打印文本文件

[英]reading and printing a text file in Perl

I have simple question: 我有一个简单的问题:

why the first code does not print the first line of the file but the second one does? 为什么第一个代码不打印文件的第一行但第二个代码呢?

#! /usr/bin/perl

use warnings;
use strict;

my $protfile = "file.txt";
open (FH, $protfile);
while (<FH>) {
         print (<FH>);

}

#! /usr/bin/perl

use warnings;
use strict;

my $protfile = "file.txt";
open (FH, $protfile);
while (my $file = <FH>) {
         print ("$file");

}

Context. 语境。

Your first program tests for end-of-file on FH by reading the first line, then reads FH in list context as an argument to print . 您的第一个程序通过读取第一行来测试FH上的文件结尾,然后在列表上下文中读取FH作为print参数。 That translates to the whole file, as a list with one line per item. 这转换为整个文件,作为每个项目一行的列表。 It then tests for EOF again, most likely detects it, and stops. 然后它再次测试EOF,很可能检测到它,然后停止。

Your second program iterates by line, each one read in scalar context to variable $file , and prints them individually. 你的第二个程序逐行迭代,每个程序在标量上下文中读取变量$file ,并单独打印它们。 It detects EOF by a special case in the while syntax. 它通过while语法中的特殊情况检测EOF。 (see the code samples in the documentation ) (参见文档中的代码示例)

So the specific reason why your program doesn't print the first line in one case is that it's lost in the argument to while . 因此,在一个案例中你的程序不打印第一行的具体原因是它在while的参数中丢失了。 Do note that the two programs' structure is pretty different: the first only runs a single while iteration, while the second iterates once per line. 请注意,这两个程序的结构非常不同:第一个只while迭代时运行一个,而第二个在每行迭代一次。

PS: nowadays, the recommended way to manage files tends towards lexical filehandles ( open my $file, 'name'; print <$file>; ). PS:现在,管理文件的推荐方法倾向于词汇文件句柄( open my $file, 'name'; print <$file>; )。

Because you are comsuming the first line with the <> operator and then using it again in the print, so the first line has already gone but you are not printing it. 因为你正在使用<>操作符来第一行,然后在打印中再次使用它,所以第一行已经消失但是你没有打印它。 <> is the readline operator. <>是readline运算符。 You need to print the $_ variable, or assign it to a defined variable as you are doing in the second code. 您需要打印$ _变量,或者像在第二个代码中那样将其分配给已定义的变量。 You could rewrite the first: 你可以重写第一个:

print; 打印;

And it would work, because print uses $_ if you don't give it anything. 它会起作用,因为如果你不给它任何东西,print会使用$ _。

When used in scalar context , <FH> returns the next single line from the file. 标量上下文中使用时, <FH>将返回文件中的下一行。

When used in list context , <FH> returns a list of all remaining lines in the file. 列表上下文中使用时, <FH>返回文件中所有剩余行的列表。

while (my $file = <FH>) is a scalar context, since you're assigning to a scalar. while (my $file = <FH>)是一个标量上下文,因为你正在分配一个标量。 while (<FH>) is short for while(defined($_ = <FH>)) , so it is also a scalar context. while (<FH>)while(defined($_ = <FH>))缩写while(defined($_ = <FH>)) ,因此它也是标量上下文。 print (<FH>); makes it a list context, since you're using it as argument to a function that can take multiple arguments. 使它成为一个列表上下文,因为你将它用作可以接受多个参数的函数的参数。

while (<FH>) {
    print (<FH>);
}

The while part reads the first line into $_ (which is never used again). while部分将第一行读入$_ (从不再使用)。 Then the print part reads the rest of the lines all at once, then prints them all out again. 然后print部件一次读取所有行,然后再次打印出来。 Then the while condition is checked again, but since there are now no lines left, <FH> returns undef and the loop quits after just one iteration. 然后再次检查while条件,但由于现在没有剩下的行, <FH>返回undef并且循环在一次迭代后退出。

while (my $file = <FH>) {
    print ("$file");
}

does more what you probably expect: reads and then prints one line during each iteration of the loop. 做更多你可能期望的事情:在循环的每次迭代中读取然后打印一行。

By the way, print $file; 顺便说一句, print $file; does the same as print ("$file"); print ("$file");

while (<FH>) {
    print (<FH>);
}

use this instead: 改用它:

while (<FH>) {
    print $_;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM