Perl - в то время как (<>) обработка файлов
Простая программа с while( <> )
обрабатывает файлы, указанные в качестве аргументов (./program 1.file 2.file 3.file
) и стандартный ввод Unix-систем.
Я думаю, что он объединяет их вместе в один файл и работает по строкам. Проблема в том, как я знаю, что я работаю с первым файлом? А затем со вторым.
Для простого примера я хочу напечатать содержимое файла в одной строке.
while( <> ){
print "\n" if (it the second file already);
print $_;
}
Ответы
Ответ 1
Оператор алмаза не объединяет файлы, он просто открывается и читает их последовательно. Как вы контролируете это, зависит от того, как вам это нужно. Простой способ проверить, когда мы прочитали последнюю строку файла, это использовать eof
:
while (<>) {
chomp; # remove newline
print; # print the line
print "\n" if eof; # at end of file, print a newline
}
Вы также можете рассмотреть счетчик, чтобы отслеживать, какой файл обрабатывается
$counter++ if eof;
Обратите внимание, что этот счет будет увеличиваться на один в последней строке файла, поэтому не используйте его преждевременно.
Если вы хотите отслеживать номер строки $.
в текущем дескрипторе файла, вы можете close
описать файл ARGV на reset этот счетчик:
while (<>) {
print "line $. : ", $_;
close ARGV if eof;
}
Ответ 2
<>
- частный случай оператора readline. Обычно он принимает дескриптор файла: <$fh>
.
Если дескриптор файла не используется, тогда используется мануал файла ARGV
.
Если аргументы командной строки не заданы, то ARGV
- STDIN
. Если заданы аргументы командной строки, то ARGV
будет open
ed для каждого из них по очереди. Это похоже на
# Pseudocode
while ($ARGV = shift @ARGV) {
open ARGV, $ARGV or do{
warn "Can't open $ARGV: $!";
next;
};
while (<ARGV>) {
...; # your code
}
}
Переменная $ARGV
вещественна и содержит имя файла открытого в данный момент файла.
Помните, что форма с двумя аргументами open
(которая, вероятно, используется здесь за кулисами), является довольно небезопасной. Имя файла rm -rf * |
может не делать то, что вы хотите.
Ответ 3
Имя текущего файла для <>
содержится в специальной переменной $ARGV
.
Вы можете перекрестно сопоставить свой список файлов из массива параметров @ARGV
с текущим именем файла, чтобы получить позицию файла в списке. Предполагая, что единственными параметрами, которые вы ожидаете, являются имена файлов, вы можете просто сделать:
my %filename_positions = map { ( $ARGV[$_] => $_ ) } 0..$#ARGV;
while (<>) {
my $file_number = $filename_positions{$ARGV};
#... if ($file_number == 0) { #first file
}