Perl one-liner: как ссылаться на имя файла, переданное при использовании ключей командной строки -ne или -pe - PullRequest
13 голосов
/ 05 февраля 2012

В Perl обычно достаточно просто получить ссылку на аргументы командной строки.Я просто использую $ARGV[0], например, чтобы получить имя файла, который был передан в качестве первого аргумента.

Однако при использовании однострочного Perl он, похоже, больше не работает.Например, здесь я хочу напечатать имя файла, который я перебираю, если в нем найдена определенная строка:

perl -ne 'print $ARGV[0] if(/needle/)' haystack.txt

Это не работает, потому что ARGV не работаетзаполняется при использовании переключателя -n или -p.Есть ли способ обойти это?

1 Ответ

22 голосов
/ 05 февраля 2012

То, что вы ищете, это $ARGV.Цитата из perlvar :

$ARGV

Contains the name of the current file when reading from <> .

Итак, ваш однострочный код станет:

perl -ne 'print $ARGV if(/needle/)' haystack.txt

Хотя имейте в виду, что он напечатает один раз для каждый совпадение.Если вы хотите добавить новую строку в печать, вы можете использовать опцию -l.

perl -lne 'print $ARGV if(/needle/)' haystack.txt

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

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

Как отмечает Питер Мортенсен, $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
    }
}

По сути, это означает, что при использовании $ARGV[0] никогда не будет отображаться реальное имя файла, поскольку оно удаляется до обращения к нему и помещается в $ARGV.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...