Perl one-liner:当使用-ne或-pe命令行开关时,如何引用传入的文件名

Mag*_*nus 13 perl command-line

在Perl中,通常很容易获得对命令行参数的引用.我只是$ARGV[0]用来获取作为第一个参数传入的文件的名称.

然而,当使用Perl单线程时,它似乎不再起作用.例如,在这里我想打印我正在迭代的文件的名称,如果在其中找到某个字符串:

perl -ne 'print $ARGV[0] if(/needle/)' haystack.txt
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为ARGV在使用-n-p切换时不会填充.有没有解决的办法?

TLP*_*TLP 23

你在寻找什么$ARGV.来自perlvar的报价:

$ARGV

Contains the name of the current file when reading from <> .
Run Code Online (Sandbox Code Playgroud)

所以,你的单行将成为:

perl -ne 'print $ARGV if(/needle/)' haystack.txt
Run Code Online (Sandbox Code Playgroud)

虽然要注意每次比赛都会打印一次.如果要在打印件中添加换行符,可以使用该-l选项.

perl -lne 'print $ARGV if(/needle/)' haystack.txt
Run Code Online (Sandbox Code Playgroud)

如果您希望每次匹配只打印一次,则可以关闭ARGV文件句柄并使其跳转到下一个文件:

perl -lne 'if (/needle/) { print $ARGV; close ARGV }' haystack.txt haystack2.txt
Run Code Online (Sandbox Code Playgroud)

正如Peter Mortensen指出的那样,$ARGV并且$ARGV[0]是两个不同的变量.$ARGV[0]指的是数组的第一个元素@ARGV,而$ARGV标量是一个完全不同的变量.

你说@ARGV使用-p-n切换时没有填充,这是不正确的.静默运行的代码类似于:

while (@ARGV) {
    $ARGV = shift @ARGV;           # arguments are removed during runtime
    open ARGV, $ARGV or die $!; 
    while (defined($_ = <ARGV>)) {  # long version of: while (<>) {
        # your code goes here
    } continue {                   # when using the -p switch
        print $_;                  # it includes a print statement
    }
}
Run Code Online (Sandbox Code Playgroud)

这实际上意味着使用$ARGV[0]永远不会显示真实的文件名,因为它在被访问和放入之前被删除$ARGV.

  • 如何将文件与例如匹配行一起打印,例如在命令 `perl -ne 'print "$ARGV: $line" if /pattern/' $(grep -rl "pattern")` 中,我应该做什么地点而不是 *$line*? (2认同)