Problème général
Je veux écrire un script qui interagit avec l'utilisateur même s'il se trouve au milieu d'une chaîne de tuyaux.
Exemple concret
Concrètement, il faut un file
ou stdin
, affiche les lignes (avec des numéros de ligne), demande à l'utilisateur de saisir une sélection ou des numéros de ligne, puis imprime les lignes correspondantes dans stdout
. Appelons ce script selector
. Alors en gros, je veux pouvoir faire
grep abc foo | selector > myfile.tmp
Si foo
contient
blabcbla
foo abc bar
quux
xyzzy abc
selector
me présente ensuite (sur le terminal, pas dedans myfile.tmp
!) des options
1) blabcbla
2) foo abc bar
3) xyzzy abc
Select options:
après quoi je tape
2-3
et finir avec
foo abc bar
xyzzy abc
comme contenu de myfile.tmp
.
J'ai un script de sélection opérationnel et, fondamentalement, il fonctionne parfaitement si je ne redirige pas l'entrée et la sortie. Donc
selector foo
se comporte comme je veux. Cependant, lors de l'assemblage des éléments comme dans l'exemple ci-dessus, selector
imprime les options présentées myfile.tmp
et essaie de lire une sélection à partir de l'entrée reçue.
Mon approche
J'ai essayé d'utiliser le -u
drapeau de read
, comme dans
exec 4< /proc/$PPID/fd/0
exec 4> /proc/$PPID/fd/1
nl $INPUT >4
read -u4 -p"Select options: "
mais cela ne fait pas ce que j'espérais.
Q: Comment obtenir une interaction réelle avec l'utilisateur?
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; }'
qui fonctionne assez bien. Mais se grep b foo | selector | wc -l
casse ici. Des idées pour réparer celà? Soit dit en passant, celui rangeselect
que j'ai utilisé se trouve sur pastebin.com/VAxTSSHs . Il s'agit d'un simple script AWK qui imprime les lignes d'un fichier correspondant à une plage donnée de linumbers. (Les plages peuvent être des choses comme "3-10, 12,14,16-20".)
alias
cela, plutôt selector() { all of that stuff...; }
dans une fonction. alias
es renomme les commandes simples tandis que les fonctions regroupent une commande composée en une seule commande simple .