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 file
ou stdin
exibe 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 foo
contém
blabcbla
foo abc bar
quux
xyzzy abc
então selector
me 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, selector
imprime as opções apresentadas myfile.tmp
e tenta ler uma seleção da entrada grepped.
Minha abordagem
Eu tentei usar a -u
bandeira 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 -l
quebra aqui. Alguma idéia de como consertar isso? A propósito, o rangeselect
que 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".)
alias
isso, sim, selector() { all of that stuff...; }
em uma função. alias
renomeia comandos simples, enquanto as funções agrupam um comando composto em um único comando simples .