Рассмотрим следующий пример игрушка (то, что я действительно делаю, более сложно), где я хочу получить две части информации из одной и той же последовательности команд:
echo 'cats pajamas
hatori hanso
batterang
catwoman
fratstar' > tmp1
answer1=$(grep 'cat' tmp1)
answer2=$(grep 'cat' tmp1 | wc -l)
По сути, я ищу способ запустить только более раннюю команду (команды) в последовательности, в данном случае grep
, один раз, при этом получая точно те же значения, которые хранятся в переменных answer1
и answer2
. Я предполагаю, что это будет работать как разделение канала (так сказать) на answer1
и на wc -l
, с выводом последнего на answer2
.
Обратите внимание, что использование прерывистой переменной или файла для хранения вывода grep
изменит то, что возвращает wc -l
. Это мотивирует мой выбор этого игрушечного примера и, я думаю, ограничивает актуальность это. Этот вопрос кажется связанным, однако мне не ясно, как можно присвоить промежуточную часть другой переменной. В настоящее время я нахожусь в bash
, хотя можно использовать альтернативные оболочки.
Используйте tee
с парой именованных каналов. (Строго говоря, вы могли бы сделать это с одним каналом и стандартным выводом самого grep
, но представление проще с двумя каналами.)
mkfifo p1 p2
grep cat tmp1 | tee p1 p2 > /dev/null &
answer1=$(cat p1)
answer2=$(wc -l < p2)
tee
разделяет вывод так, как вы хотите, записывая его в два отдельных канала, из которых cat
и wc -l
считываются независимо позже.
Я предполагаю, что это более применимо к вашему варианту использования, чем answer1=$(grep 'cat' tmp1)
и answer2=$(echo "$answer1" | wc -l)
.
Я решил это, и это работает, как и ожидалось, спасибо. Я думаю, что что-то все еще держалось за fifo. Чтобы надеть на него лук, вы можете пересмотреть свой ответ, чтобы очистить p1
и p2
?
Кажется, что это зависает в строке
answer1=...
, хотя кажется, чтоp1
должна была быть открыта для чтения и записи в этот момент... если я добавлю&
в конец этой строки, она завершается, однакоanswer1
кажется пустым. Расследование...