Курс Raku / Об’єкти, введення-виведення та винятки / Введення та виведення / Запуск зовнішніх програм 🆕

Захоплення виведення

Щоб прочитати те, що виводить зовнішня програма, замість пускати це на екран, передайте :out під час запуску. Повернений Proc тоді має дескриптор .out, з якого можна читати:

my $proc = run 'echo', 'hello', :out;
my $output = $proc.out.slurp(:close);
say $output.chomp; # hello

:out перенаправляє стандартний вивід програми в Proc. Дескриптор .out працює як дескриптори файлів із попереднього розділу, а .slurp зчитує з нього все за раз. Наріччя :close є зручним скороченням: після читання воно закриває дескриптор за вас — те саме прибирання, яке ви явно робили через .close для дескриптора файлу, — тож нічого не лишається відкритим. Нарешті .chomp прибирає завершальний перехід рядка, який додає echo.

Так само працює й shell, що стає в пригоді для перехоплення результату конвеєра:

my $proc = shell 'echo hello | tr a-z A-Z', :out;
say $proc.out.slurp(:close).chomp; # HELLO

Перехопити можна й потік помилок — через :err і відповідний дескриптор .err. Передача одразу :out і :err тримає ці два потоки нарізно, кожен у своєму дескрипторі, тож їх можна читати окремо:

my $proc = run 'sh', '-c', 'echo out-line; echo err-line >&2', :out, :err;

say 'stdout: ', $proc.out.slurp(:close).chomp; # stdout: out-line
say 'stderr: ', $proc.err.slurp(:close).chomp; # stderr: err-line

Тут команда оболонки виводить один рядок у стандартний вивід і один — у стандартний потік помилок (>&2 туди перенаправляє). Оскільки ми попросили обидва потоки, .out та .err тримають їх незалежно — звичайний вивід програми ніколи не змішується з її діагностикою.

Перехоплення виводу — це спосіб використати зовнішню програму як будівельний блок: запустити її, прочитати результат і рушити далі з цими даними у власній програмі.

Навігація курсом

Тест — Запуск програм   |   Об’єкт Proc


💪 Або перейдіть одразу до вправ цього розділу.