Problema geral
Quero escrever um script que interaja com o usuário, mesmo que esteja no meio de uma cadeia de tubos.
Exemplo concreto
Concretamente, ele pega a fileou stdinexibe linhas (com números de linha), solicita ao usuário que insira uma seleção ou números de linha e imprime as linhas correspondentes em stdout. Vamos chamar esse script selector. Então, basicamente, eu quero poder fazer
grep abc foo | selector > myfile.tmp
Se foocontém
blabcbla
foo abc bar
quux
xyzzy abc
então selectorme apresenta (no terminal, não no myfile.tmp!) opções
1) blabcbla
2) foo abc bar
3) xyzzy abc
Select options:
após o que eu digito
2-3
e acabar com
foo abc bar
xyzzy abc
como conteúdo de myfile.tmp.
Eu tenho um script seletor instalado e funcionando, e basicamente funciona perfeitamente se eu não redirecionar a entrada e a saída. assim
selector foo
se comporta como eu quero. No entanto, ao canalizar as coisas juntas, como no exemplo acima, selectorimprime as opções apresentadas myfile.tmpe tenta ler uma seleção da entrada grepped.
Minha abordagem
Eu tentei usar a -ubandeira de read, como em
exec 4< /proc/$PPID/fd/0
exec 4> /proc/$PPID/fd/1
nl $INPUT >4
read -u4 -p"Select options: "
mas isso não faz o que eu esperava.
P: Como obtenho uma interação real do usuário?
cmd | { some processing; read var </dev/tty; } | cmd
alias selector='{ TMPFILE=$(mktemp); cat > $TMPFILE; nl -s") " $TMPFILE | column -c $(tput cols); read -e -p"Select options: " < /dev/tty; rangeselect -v range="$REPLY" $TMPFILE; rm $TMPFILE; }'que funciona muito bem. No entanto grep b foo | selector | wc -lquebra aqui. Alguma idéia de como consertar isso? A propósito, o rangeselectque eu usei pode ser encontrado em pastebin.com/VAxTSSHs . É um script AWK simples que imprime as linhas de um arquivo correspondente a um determinado intervalo de números de roupa. (Os intervalos podem ser coisas como "3-10, 12,14,16-20".)
aliasisso, sim, selector() { all of that stuff...; }em uma função. aliasrenomeia comandos simples, enquanto as funções agrupam um comando composto em um único comando simples .