2013-02-17 3 views
15

Простая программа с while(<>) обрабатывает файлы, указанные в качестве аргументов (./program 1.file 2.file 3.file) и стандартный ввод Unix-систем.Perl - while (<>) обработка файлов

Я думаю, что он объединяет их вместе в один файл и работает по строкам. Проблема в том, как я знаю, что я работаю с первым файлом? А потом со вторым.

Для простого примера я хочу напечатать содержимое файла в одной строке.

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

выглядит так похож на следующий С.О. тему: HTTP: //stackoverflow.com/questions/13584944/which-file-is-perl-diamond-operator-currently-reading-from – varnie

ответ

18

оператор Алмаз не конкатенации файлов, он просто открывает и читает их последовательно. Как вы контролируете это, зависит от того, как вам это нужно. Простой способ проверить, когда мы читали последнюю строку файла использовать 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 дескриптор файла для сброса счетчика:

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

Спасибо, ваш ответ помог много! –

+0

@MantasMarcinkus Добро пожаловать. – TLP

+0

См. 'Perldoc -f eof' для получения дополнительной информации об обнаружении границ между файлами, считанными оператором' <>. – chepner

10

<> является специальным случаем оператора readline. Обычно он принимает дескриптор файла: <$fh>.

Если дескриптор файла не указан, тогда используется мануала magic 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 * | может не делать то, что вы хотите.

1

Название текущего файла для <> содержится в специальном $ARGVvariable.

Вы можете перекрестно сопоставить свой список файлов с массивом параметров @ARGV с текущим именем файла, чтобы получить позицию файла в списке. Если предположить, что только те параметры, которые вы ожидаете являются имена файлов, вы можете просто сделать:

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

while (<>) { 
    my $file_number = $filename_positions{$ARGV}; 
    #... if ($file_number == 0) { #first file  
} 
Смежные вопросы