Как мне добавить поток в Bash?

Предположим, у меня есть следующая команда в bash:

one | two

one работает в течение длительного времени, создавая поток вывода, а two выполняет быструю операцию с каждой строкой этого потока, но two вообще не работает, если только первое прочитанное значение не указывает, сколько значений нужно прочитать в строке. one не выводит это значение, но я заранее знаю, что это такое (допустим, это 15). Я хочу отправить 15\n через канал до вывода one. Я не хочу изменять one или two.

Первой мыслью было сделать:

echo "$(echo 15; one)" | two

Это дает мне правильный вывод, но он вообще не проходит через канал, пока команда one не завершится. Я хочу, чтобы вывод сразу же начал передаваться по каналу, так как его выполнение занимает много времени (месяцы).

Я также пробовал:

echo 15; one | two

Который, конечно же, выдает 15, но не отправляет его по каналу в two.

Есть ли способ в bash передать «15\n» через канал, а затем начать потоковую передачу one через тот же канал?


person Paul    schedule 28.06.2013    source источник
comment
Вы пробовали группировать? { echo 15; one; } | two   -  person gniourf_gniourf    schedule 29.06.2013


Ответы (3)


Вам просто нужна конструкция группировки оболочки:

{ echo 15; one; } | two

Пробелы вокруг фигурных скобок и завершающая точка с запятой обязательны.

Тестировать:

one() { sleep 5; echo done; }
two() { while read line; do date "+%T - $line"; done; }
{ printf "%s\n" 1 2 3; one; } | two
16:29:53 - 1
16:29:53 - 2
16:29:53 - 3
16:29:58 - done
person glenn jackman    schedule 28.06.2013
comment
Я +1 вас только потому, что вы упомянули Обязательны пробелы вокруг фигурных скобок и завершающая точка с запятой (что было бы целью другого вопроса), а я этого не сделал. :) - person gniourf_gniourf; 29.06.2013

Используйте группировку команд:

{ echo 15; one; } | two

Сделанный!

person gniourf_gniourf    schedule 28.06.2013

Вы можете сделать это с помощью sed:

Пример сценария «один», выдает одну строку в секунду, чтобы показать, что строка буферизована и работает.

#!/bin/bash
while [ 1 ]; do
    echo "TICK $(date)"
    sleep 1
done

Затем передайте это через эту команду sed, обратите внимание, что для вашего конкретного примера «ArbitraryText» будет количеством полей. Я использовал ArbitraryText, чтобы было очевидно, что это вставленный текст. В OSX -l не буферизируется с помощью GNU Sed, я думаю, это -u

 $ ./one | sed -l '1i\
> ArbitraryText
> '

Что это делает, так это указывает sed вставить одну строку перед обработкой остальной части вашего файла, все остальное пройдет без изменений.

Конечный результат обрабатывается построчно без буферизации фрагментов (или ожидания завершения входного скрипта).

ArbitraryText
TICK Fri Jun 28 13:26:56 PDT 2013
...etc

Затем вы сможете передать это в «два», как обычно.

person synthesizerpatel    schedule 28.06.2013