Как мне сохранить значение, возвращаемое либо 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"). Эта форма цитирования строк интерполирует, что означает, что она подвергается атаке внедрения кода, если вы включаете переменную в строку, передаваемую в оболочку.

Другие вопросы по тегам