До сих пор я знал механизм конвейеризации как способ соединения серии команд путем соединения stdout одной команды со stdin следующей команды до тех пор, пока не будет достигнута последняя команда, которая соединит свой stdout с дисплеем или файлом.
Однако возможно ли создать цикл из команд, так чтобы стандартный вывод последней команды соединялся со стандартным вводом первой команды и, может быть, с помощью tee можно было бы как-то отобразить изменяющиеся значения определенного вывода?
решение1
Я не уверен насчет всех оболочек, которые есть, но в Bash это возможно, хотя и не с безымянными каналами. Так что не с символом |
. Но если вы создадите именованный канал:
mkfifo fifo
Тогда вы можете использовать это:
<fifo cat | cat >fifo &
Теперь трубопровод работает в фоновом режиме, но ничего не делает. Но если вы подадите в трубопровод данные извне:
echo x >fifo
Трубопровод разблокируется и будет работать вечно. Или пока вы не осушит трубу:
cat fifo
Вывод появится один раз:
x
Если немного усложнить, то конвейер может быть таким:
<fifo cat | xargs -I@ echo @x >fifo &
Итак, он будет добавлять x
к выходу на каждой итерации. Конечно, так и будет, но только после начала итераций, то есть как только канал разблокируется, то есть как только будет что-то читать. Как и раньше, это можно запустить вручную:
echo x >fifo
А теперь посмотрите, что top
показывает. Должно быть довольно много активности и у , и cat
у xargs
.
И так же, как и раньше, если вы осушаете трубопровод, вы увидите много x
S в терминале, и трубопровод заблокируется.
Это был бы обоснованный вопрос, почему трубопровод опустошается. Почему команда, cat
зафиксированная в терминале, не оставляет ничего в цепи. Я этого не знаю.
решение2
Конечно, вы могли бы просто создать цикл и использовать переменные:
while true; do
a=$(echo "$a" | grep "Hey" | cut -d" " -f2 | tee -a log)
done
Это сохранит последний вывод, который будет снова использован в начале.
решение3
Как уже было сказано, зацикленный конвейер невозможен в оболочке Unix без использования именованного канала (созданного с помощьюmkfifo(1)). Но вы можете сделать это на C; например, вот мойгрязно-простая реализация, который даже не дождался завершения процессов.
Я надеюсь вы найдете эту информацию полезной.