9

如果awk我将多个文件作为参数提供给awk,则有两个特殊变量:

NR= 对应于所有文件中所有行的行号。

FNR=当前文件的行号。

我知道在 Perl 中,$.对应于NR(所有文件中的行中的当前行)。

Perl 中是否也有与FNRAWK 类似的东西?

假设我有一些命令行:

perl -pe 'print filename,<something special which hold the current file's line number>'  *.txt

这应该给我这样的输出:

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

3 回答 3

6

实际上,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
于 2012-09-12T09:47:26.357 回答
5

Perl 中没有这样的变量。但是你应该学习eof才能写出类似的东西

perl -ne 'print join ":", $. + $sum, $., "\n"; $sum += $., $.=0  if eof;' *txt
于 2012-09-12T09:30:02.427 回答
0

我发现这种情况是使用 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 正则表达式,我只会使用awkor git grep -P。但是,如果您正在处理一个相当复杂的正则表达式,或者需要其他 Perl 功能,那将无法正常工作……并且这个问题的正确答案会使已经很可能是复杂的 Perl 单行代码变得更加复杂。

所以我只使用以下内容:

git ls-files -z | xargs -0 -n1 perl -ne 'print "$ARGV:$.\t$_" if /#define oom/'

file.h:43       #define oom() exit(-1)

xargs 参数使-n1xargs 为每个文件启动一个 Perl 进程,从而产生正确的行号。您正在查看非常显着的性能影响,但我发现它对于具有数百万行代码的非常大的项目而不是在 Perl 中解决它是可以接受的,我发现这几乎总是需要一个实际的脚本而不是单行代码。在绝大多数情况下,系统范围的搜索是不可接受的。

于 2018-07-16T22:08:25.193 回答