Как мне сохранить значение, возвращаемое либо run, либо shell?
Допустим, у меня есть этот скрипт:
# prog.p6
my $info = run "uname";
Когда я бегу prog.p6
, Я получил:
$ perl6 prog.p6
Linux
Есть ли способ сохранить строковую версию возвращаемого значения и предотвратить его вывод на терминал?
Уже есть похожий вопрос, но он не дает конкретного ответа.
3 ответа
Вам нужно включить канал stdout, который по умолчанию имеет значение $*OUT
, установив :out
, Так:
my $proc = run("uname", :out);
my $stdout = $proc.out;
say $stdout.slurp;
$stdout.close;
который можно сократить до:
my $proc = run("uname", :out);
say $proc.out.slurp(:close);
Если вы хотите захватить вывод на stderr отдельно от stdout, вы можете сделать:
my $proc = run("uname", :out, :err);
say "[stdout] " ~ $proc.out.slurp(:close);
say "[stderr] " ~ $proc.err.slurp(:close);
или если вы хотите захватить stdout и stderr в один канал, то:
my $proc = run("uname", :merge);
say "[stdout and stderr] " ~ $proc.out.slurp(:close);
Наконец, если вы не хотите захватывать вывод и не хотите выводить его на терминал:
my $proc = run("uname", :!out, :!err);
exit( $proc.exitcode );
По умолчанию run
просто проходит STDOUT
а также STDERR
для родительского процесса STDOUT
а также STDERR
,
Вы должны сказать это, чтобы сделать что-то еще.
Самое простое - просто дать :out
сказать это сохранить STDOUT
, (Короче для :out(True)
)
my $proc = run 'uname', :out;
my $result = $proc.out.slurp(:close);
my $proc = run 'uname', :out;
for $proc.out.lines(:close) {
.say;
}
Вы также можете эффективно сказать это просто отправить STDOUT
в /dev/null
с :!out
, (Короче для :out(False)
)
Есть еще вещи, которые вы можете сделать с :out
{
my $file will leave {.close} = open :w, 'test.out';
run 'uname', :out($file); # write directly to a file
}
print slurp 'test.out'; # Linux
my $proc = run 'uname', :out;
react {
whenever $proc.out.Supply {
.print
LAST {
$proc.out.close;
done; # in case there are other whenevers
}
}
}
Если вы собираетесь сделать это в последний раз, вероятно, лучше использовать Proc::Async.
Решение, описанное в этом ответе, является кратким.
Это иногда перевешивает его недостатки:
Не хранит код результата. Если вам это нужно, используйте вместо этого решение ugexe.
Не сохраняет вывод в stderr. Если вам это нужно, используйте вместо этого решение ugexe.
Потенциальная уязвимость. Это объясняется ниже. Рассмотрите решение ugexe вместо этого.
Документация по функциям, описанным ниже, начинается с наречий цитаты :exec
,
Самый безопасный небезопасный вариант: q
Самый безопасный вариант использует один q
:
say qx[ echo 42 ] # 42
Если есть ошибка, то конструкция возвращает пустую строку, и любое сообщение об ошибке появится в stderr.
Этот самый безопасный вариант аналогичен одиночной строке в кавычках, например 'foo'
перешел в оболочку. Строки в одинарных кавычках не интерполируются, поэтому нет уязвимости к атаке внедрения кода.
Тем не менее, вы передаете единственную строку в оболочку, которая может не соответствовать ожидаемой, поэтому она может не анализировать строку, как вы ожидали.
Наименее безопасный небезопасный вариант: qq
Следующая строка дает тот же результат, что и q
линия, но использует наименее безопасный вариант:
say qqx[ echo 42 ]
Этот двойной q
вариант аналогичен строке в двойных кавычках ("foo"
). Эта форма цитирования строк интерполирует, что означает, что она подвергается атаке внедрения кода, если вы включаете переменную в строку, передаваемую в оболочку.