#bash
Вопрос:
Например, предположим, что вызвана программа foo
, и программа печатает новую строку, когда захочет. Как я могу запустить другую программу, когда foo
печатается новая строка?
foo
пример:
while true; do echo hi sleep 1 done
я не могу редактировать foo
Комментарии:
1. Можете ли вы уточнить, что вы подразумеваете под «новой строкой»? Возможно, это хорошая возможность для более длинного сценария оболочки, использующего цикл while. Интересно, могли бы вы сделать однострочную прокладку, используя
watch
иdiff
и множество операторов труб.2. Я не думаю, что могу использовать цикл while, потому что сама программа foo является чем-то вроде цикла while, она выдает результат всякий раз, когда обнаруживает изменение. Я не хочу использовать часы, потому что я не хочу никакой задержки.
3. Используйте
read
встроенное, см.help read
Ответ №1:
Вот функция, которая, я думаю, послужит вашей цели:
function my_function { while true; do read amp;amp; "$@" ; done ; }
Чтобы запускать программу prog
каждый раз, когда программа foo
выводит строку, вы можете написать это на терминале:
foo | my_function prog
Если вы хотите передать arg1
и arg2
в качестве аргументов «прогу», вы можете назвать это так (спасибо @Ульрих Экхардт и @Гленн Джекман):
foo | my_function prog arg1 arg2
Комментарии:
1. куда мне позвонить фу?
2.
foo | my_function "echo hello"
— вы передаете выводfoo
в программу, реагирующую на его вывод.3. Я бы предложил:
my_function() { while true; do read amp;amp; "$@"; done; }
тогда вы можете отправлять любые произвольные аргументы, даже содержащие пробелы:foo | my_function prog "arg the first" "arg the second"
4. Как предложил @glennjackman, пожалуйста, отредактируйте свой ответ и замените
$@
на"$@"
, иначе я понижу ваш голос 😛5. Да, всегда цитируйте
"$@"
, если только вы точно не знаете, что произойдет, если вы этого не сделаете.
Ответ №2:
Как уже предлагалось в комментариях, вы можете использовать while read
для выполнения итерации цикла для каждой строки вывода foo
.
foo | while IFS= read -r line; do # maybe echo "$line"? echo "hi" done
Существуют опции read
, позволяющие использовать разделитель ввода, отличный от новой строки.
Это можно было бы значительно упростить, если бы вы действительно заботились только о том, чтобы что-то делать, когда приходит строка, но не о фактическом выводе перед новой строкой. -r
Опция и IFS=
назначение помогают сохранить точное содержимое line
внутри цикла (в частности, IFS=
не позволяет оболочке удалять пробелы из входного значения, а -r
опция отключает синтаксический анализ обратных косых черт, чего вы обычно не хотите).