Perl - while (<>) file handling [duplicate]

删除回忆录丶 提交于 2019-12-31 10:36:20

问题


A simple program with while( <> ) handles files given as arguments (./program 1.file 2.file 3.file) and standard input of Unix systems.

I think it concatenates them together in one file and work is line by line. The problem is, how do I know that I'm working with the first file? And then with the second one.

For a simple example, I want to print the file's content in one line.

while( <> ){
    print "\n" if (it's the second file already);
    print $_;
}

回答1:


The diamond operator does not concatenate the files, it just opens and reads them consecutively. How you control this depends on how you need it controlled. A simple way to check when we have read the last line of a file is to use eof:

while (<>) {
    chomp;             # remove newline
    print;             # print the line
    print "\n" if eof; # at end of file, print a newline
}

You can also consider a counter to keep track of which file in order you are processing

$counter++ if eof;

Note that this count will increase by one at the last line of the file, so do not use it prematurely.

If you want to keep track of line number $. in the current file handle, you can close the ARGV file handle to reset this counter:

while (<>) {
    print "line $. : ", $_;
    close ARGV if eof;
}



回答2:


The <> is a special case of the readline operator. It usually takes a filehandle: <$fh>.

If the filehandle is left out, then the the magic ARGV filehandle is used.

If no command line arguments are given, then ARGV is STDIN. If command line arguments are given, then ARGV will be opened to each of those in turn. This is similar to

# Pseudocode
while ($ARGV = shift @ARGV) {
  open ARGV, $ARGV or do{
    warn "Can't open $ARGV: $!";
    next;
  };
  while (<ARGV>) {
    ...; # your code
  }
}

The $ARGV variable is real, and holds the filename of the file currently opened.

Please be aware that the two-arg form of open (which is probably used here behind the scenes), is quite unsafe. The filename rm -rf * | may not do what you want.




回答3:


The name of the current file for <> is contained in special $ARGV variable.

You can cross-match your list of files from @ARGV parameter array with current file name to get the file's position in the list. Assuming the only parameters you expect are filenames, you can simply do:

my %filename_positions = map { ( $ARGV[$_] => $_ ) } 0..$#ARGV;

while (<>) {
    my $file_number = $filename_positions{$ARGV};
    #... if ($file_number == 0) { #first file     
}


来源:https://stackoverflow.com/questions/14922272/perl-while-file-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!