Номер строки файла в Perl

на awk Если я дам более одного файла в качестве аргумента awk, есть две специальные переменные:

NR=номер строки, соответствующий всем строкам во всех файлах.

FNR=номер строки текущего файла.

Я знаю, что в Perl, $. соответствует NR (текущая строка среди строк во всех файлах).

есть ли что-нибудь сравнимое с FNR AWK в Perl тоже?

Давайте я некоторая командная строка:
perl -pe 'print filename,<something special which hold the current file's line number>'  *.txt

это должно дать мне выходной, как:

file1.txt 1
file1.txt 2
file2.txt 1

3 ответов


в Perl нет такой переменной. Но вы должны учиться!--2-->eof уметь писать что-то вроде

perl -ne 'print join ":", $. + $sum, $., "\n"; $sum += $., $.=0  if eof;' *txt

на самом деле eof документация показывает способ сделать это:

# reset line numbering on each input file
while (<>) {
    next if /^\s*#/;  # skip comments
    print "$.\t$_";
} continue {
    close ARGV if eof;  # Not eof()!
}

пример однострочной печати первой строки всех файлов:

$ perl -ne 'print "$ARGV : $_" if $. == 1; } continue { close ARGV if eof;' *txt

Я считаю, что эта ситуация является очень большим недостатком использования Perl. Хотя этот ответ является неоптимальным, с точки зрения производительности и подходит только для ситуаций, связанных с xargs, Я обычно находил его обходным путем, который я использую 95% времени. Итак, сценарий проблемы:

£ git ls-files -z | xargs -0 perl -ne 'print "$ARGV:$.\t$_" if /#define oom/'
file.h:85806    #define oom() exit(-1)

этот номер строки, очевидно, не правильный, и вы, очевидно, получите такое же поведение с find конечно, с этим регулярным выражением или другими более простыми регулярными выражениями perl я бы просто использовал awk или git grep -P. Однако если вы имеете дело с довольно сложным регулярным выражением или нуждаетесь в других функциях perl, которые не будут работать...и правильно ответы на этот вопрос еще больше усложняют то, что уже, вероятно, будет сложным Perl one-liner.

поэтому я просто использую следующее:

£ git ls-files -z | xargs -0 -n1 perl -ne 'print "$ARGV:$.\t$_" if /#define oom/'
file.h:43       #define oom() exit(-1)

на -n1 аргумент xargs заставляет xargs запускать процесс perl для каждого файла, что приводит к правильным номерам строк. Ты смотришь на очень значительное влияние на производительность, но я нашел его приемлемым для очень больших проектов с миллионами строк кода против его решения в perl, что я нахожу почти всегда требует фактического сценария против однострочного. Это не приемлемо для системы поиска в подавляющем большинстве случаев.