используйте оператор perl's qx {} / `...` со списком аргументов - PullRequest
0 голосов
/ 02 февраля 2019

system, exec, open '|-', open2 и т. Д. Позволяют указать команду для запуска в виде списка аргументов, которые будут переданы непосредственно в execvp вместо запуска через оболочку.

Даже если perl достаточно умен, чтобы запускать его напрямую, если он выглядит как «простая» команда, это избавляет меня от необходимости правильно экранировать аргументы со всеми неприятными ловушками, которые это влечет за собой.

Пример:

open my $out, '|-', $prog, @args;
system $prog, @args;
exec $prog, @args;

вместо

open my $out, "|$prog @args";
system "$prog @args";
exec "$prog @args";

Есть ли такой эквивалент для оператора qx//?Или вы всегда должны делать это вручную, например.

sub slurpcmd {
   open my $h, '-|', @_ or die "open $_[0]|: $!";
   local $/ unless wantarray;
   <$h>
}

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Вот несколько простых опций.

Первое решение включает оболочку, но ни одно из остальных.

0 голосов
/ 03 февраля 2019

Оказывается, что (к сожалению) это не было упущено с моей стороны - единственное решение на самом деле состоит в том, чтобы сделать это с open -| или использовать один из внешних модулей, перечисленных в других ответах.

Реализация обратного ключа (независимо от того, вызвана ли она qx/.../, `...` или readpipe) глубоко спрятана для принятия единственного строкового аргумента:

PP(pp_backtick)
{
    dSP; dTARGET;
    PerlIO *fp;
    const char * const tmps = POPpconstx;
    const U8 gimme = GIMME_V;
    const char *mode = "r";

    TAINT_PROPER("``");
    if (PL_op->op_private & OPpOPEN_IN_RAW)
        mode = "rb";
    else if (PL_op->op_private & OPpOPEN_IN_CRLF)
        mode = "rt";
    fp = PerlProc_popen(tmps, mode);
    ...

Обратите внимание наPOPpconstx, который извлекает один аргумент из стека и использует PerlProc_popen вместо PerlProc_popen_list.

0 голосов
/ 02 февраля 2019

Форма списка оператора qx предоставляется модулем IPC :: System :: Simple в качестве функции capturex (дополнительно, как и другие функции в этом модуле, он выдаст исключение, еслиимеется ошибка выполнения или ненулевой код ответа, который можно настроить).В качестве альтернативы вы можете использовать Capture :: Tiny , чтобы обернуть базовый вызов system и обеспечить такое же поведение, но у него также есть другие функции, которые могут обернуть STDERR вместе или отдельно от STDOUT.

use strict;
use warnings;
use IPC::System::Simple 'capturex';
my $output = capturex $prog, @args;

use Capture::Tiny 'capture_stdout';
my ($output, $exit) = capture_stdout { system $prog, @args };
# standard system() error checking required here

В основном открытие канала по большей части является единственным вариантом, кроме IPC :: Open3 , который аналогично сложен, но позволяет также направлять STDERR.

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