Что делает символ `` 'в Perl? - PullRequest
0 голосов
/ 23 апреля 2011

Я использовал Perl для чтения каждой строки файла.Я использовал инструмент командной строки для вызова службы и заметил некоторые интересные функции, которые я не могу понять, как искать.Переменной $cmd я назначил команду, которая вызывает службу.Если я ссылаюсь на $cmd позже в коде, он выводит аргумент командной строки, но если я ссылаюсь на него как `$cmd`, то, тем не менее, он выдает результат запуска службы.

Что такоеобъяснение этому?

Ответы [ 3 ]

8 голосов
/ 23 апреля 2011

Он работает так же, как обратные кавычки в оболочке, поэтому его так и называют.Смотрите sh (1) для деталей.Он захватывает только стандартный вывод и ничего больше.Он устанавливает переменную $? в 16-битное слово состояния ожидания.

Все это объясняется в справочной странице perlop (1) :

qx/STRING/
`STRING`
Строка, которая (возможно) интерполируется и затем выполняется как системная команда с /bin/sh или ееэквивалент.Подстановочные знаки, трубы и перенаправления будут выполнены.Собранный стандартный вывод команды возвращается;стандартная ошибка не изменяетсяВ скалярном контексте он возвращается в виде одной (потенциально многострочной) строки или undef, если команда не выполнена.В контексте списка возвращает список строк (однако вы определили строки с $/ или $INPUT_RECORD_SEPARATOR) или пустой список, если команда не выполнена.

Поскольку обратные пометки делаютне влияет на стандартную ошибку: используйте синтаксис дескриптора файла оболочки (при условии, что оболочка это поддерживает), если вы хотите решить эту проблему.Чтобы захватить команды STDERR и STDOUT, объединенные вместе:

$output = `cmd 2>&1`;

Чтобы захватить команду STDOUT, но сбросить ее STDERR:

$output = `cmd 2>/dev/null`;

Чтобы захватить командуSTDERR но сбросьте его STDOUT (упорядочение здесь важно):

$output = `cmd 2>&1 1>/dev/null`;

Для обмена STDOUT и STDERR команды, чтобы захватить STDERR, но оставить ее STDOUTвыйти из старого STDERR:

$output = `cmd 3>&1 1>&2 2>&3 3>&-`;

Чтобы прочитать STDOUT команды и ее STDERR по отдельности, проще всего перенаправить их отдельно в файлы, а затем прочитать из этих файлов, когдаПрограмма завершена:

 system("program args 1>program.stdout 2>program.stderr");

Файловый дескриптор STDIN, используемый командой, унаследован от Perl STDIN.Например:

open(BLAM, "blam")     || die "$0: can't open blam: $!";
open (STDIN, "<&BLAM") || die "$0: can't dup BLAM: $!";
print `sort`;

напечатает отсортированное содержимое файла blam.

Использование одинарной кавычки в качестве разделителя защищает команду от интерполяции двойной кавычки Perl, передавая содержимоевместо этого:

$perl_info  = qx(ps $$);    # that's Perl's $$
$shell_info = qx'ps $$';    # that's the new shell's $$

То, как эта строка будет оценена, полностью зависит от интерпретатора команд в вашей системе.На большинстве платформ вам придется защищать метасимволы оболочки, если вы хотите, чтобы они обрабатывались буквально.На практике это трудно сделать, так как неясно, каким персонажам нужно бежать или как.См. perlsec для чистого и безопасного примера руководства fork и exec для безопасной эмуляции обратных ударов.На некоторых платформах (особенно DOS-подобных) оболочка может не справляться с многострочными командами, поэтому добавление новых строк в строку может не дать вам того, что вы хотите.Вы можете оценить несколько команд в одной строке, разделив их символом-разделителем команд, если ваша оболочка поддерживает это (например, ; во многих оболочках Unix; & в Windows NT CMD.COM shell).

Начиная с v5.6.0, Perl пытается очистить все файлы, открытые для вывода, перед запуском дочернего процесса, но это может не поддерживаться на некоторых платформах (см. perlport (1) ).Для безопасности вам может потребоваться установить $| ($AUTOFLUSH на английском языке) или вызвать метод autoflush для IO :: Handle на любых открытых дескрипторах.

Помните, что некоторые командные оболочки могут накладывать ограничения на длину командной строки.Вы должны убедиться, что ваш улкольца не превышают этот предел после любых необходимых интерполяций.См. примечания к выпуску для конкретной платформы для получения более подробной информации о вашей конкретной среде.

Использование этого оператора может привести к программам, которые трудно портировать, поскольку вызываемые команды оболочки различаются в разных системах, иможет фактически не присутствовать вообще.Например, команда type в оболочке POSIX сильно отличается от команды type в DOS.Это не значит, что вы должны стараться изо всех сил избегать обратных ударов, когда они являются правильным способом сделать что-то.Perl был создан, чтобы быть клеевым языком, и одна из вещей, которые он склеивает, - это команды.Просто поймите, во что вы ввязываетесь.

Подробнее см. Операторы ввода-вывода .

Вот простой пример использования обратных галочек для получениястатус выхода первого элемента в конвейере:

$device = q(/dev/rmt8);
$dd_noise = q(^[0-9]+\+[0-9]+ records (in|out)$);
$status = `exec 3>&1; ((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |  egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`;

EDIT

Хорошо, тогда, возможно, это был не , а простой пример.:) Но этот есть.

Я бы порекомендовал Capture :: Tiny CPAN модуль в качестве более простого способа управления выводом из внешних команд, которые вы обычно запускаете с использованием обратных кавычек.У него есть свои преимущества и недостатки, но я чувствую, что для многих людей преимущества перевешивают любой спорный недостаток. L

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

  • Недостаток в том, что это еще один неосновнойзависимость - что-то еще, что вы должны установить из CPAN.

Это действительно неплохо для того, что вы получаете.

Вот пример того, как это просто:

ИМЯ

Захват :: Tiny - Захват STDOUT и STDERR из Perl, XS или внешние программы

СИНОПСИС

    use Capture::Tiny qw/capture tee capture_merged tee_merged/;

     ($stdout, $stderr) = capture {
        # your code here
      };

     ($stdout, $stderr) = tee {
        # your code here
      };

     $merged = capture_merged {
        # your code here
      };

     $merged = tee_merged {
        # your code here
      };

ОПИСАНИЕ

Capture :: Tiny обеспечиваетпростой переносимый способ захвата всего, что отправлено в STDOUT или STDERR, независимо от того, прибывает ли оно из Perl, из XSкод или из внешней программы.При желании, вывод может быть передан так, чтобы он был захвачен во время передачи на оригинальные дескрипторы.Да, это работает даже на Windows .Перестаньте гадать, какой из дюжины модулей захвата использовать в любой конкретной ситуации, и просто используйте этот.

Не правда ли, намного проще?

3 голосов
/ 23 апреля 2011

Обратные кавычки в Perl во многом аналогичны обратным кавычкам в оболочке - они запускают команду и записывают стандартный вывод.

См. Также qx // .

0 голосов
/ 23 апреля 2011

Я думаю, что backtick позволяет вам запускать команды и сохранять их вывод в переменной:

$listing=`ls -1 /tmp/`;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...