A construção <(…)
cria um canal. O pipe é passado por meio de um nome de arquivo como /dev/fd/63
, mas esse é um tipo especial de arquivo: abri-lo realmente significa duplicar o descritor de arquivo 63. (Veja o final de esta resposta para mais explicações.)
Ler de um pipe é uma operação destrutiva: uma vez que você pegou um byte, você não pode jogá-lo de volta. Portanto, seu script precisa salvar a saída do pipe. Você pode usar um arquivo temporário (preferível se a entrada for grande) ou uma variável (preferível se a entrada for pequena). Com um arquivo temporário:
tmp=$(mktemp)
cat <"$1" >"$tmp"
cat <"$tmp"
grep hello <"$tmp"
sed 's/hello/world/g' <"$tmp"
rm -f "$tmp"
(Você pode combinar as duas chamadas para cat
como tee <"$1" -- "$tmp"
.) Com uma variável:
tmp=$(cat)
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'
Observe que a substituição de comandos $(…)
trunca todas as novas linhas no final da saída do comando. Para evitar isso, adicione um caractere extra e retire-o depois.
tmp=$(cat; echo a); tmp=${tmp%a}
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'
A propósito, não esqueça as aspas duplas em torno das substituições de variáveis.