Курс языка программирования 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


💪 Или перейдите сразу к упражнениям этого раздела.