Allgemeines Problem
Ich möchte ein Skript schreiben, das mit dem Benutzer interagiert, obwohl es sich mitten in einer Rohrkette befindet.
Konkretes Beispiel
Konkret dauert es ein file
oder stdin
, zeigt Zeilen (mit Zeilennummern) an, fordert den Benutzer auf, eine Auswahl oder Zeilennummern einzugeben, und druckt dann die entsprechenden Zeilen aus stdout
. Nennen wir dieses Skript selector
. Dann möchte ich im Grunde in der Lage sein zu tun
grep abc foo | selector > myfile.tmp
Wenn foo
enthält
blabcbla
foo abc bar
quux
xyzzy abc
dann selector
präsentiert mir (auf dem terminal, nicht in myfile.tmp
!) optionen
1) blabcbla
2) foo abc bar
3) xyzzy abc
Select options:
Danach tippe ich ein
2-3
und am Ende mit
foo abc bar
xyzzy abc
als Inhalt von myfile.tmp
.
Ich habe ein Auswahlskript eingerichtet, und im Grunde funktioniert es perfekt, wenn ich Ein- und Ausgabe nicht umleitung. So
selector foo
benimmt sich wie ich will. Wenn Sie jedoch Dinge wie im obigen Beispiel zusammenfügen, werden selector
die dargestellten Optionen gedruckt myfile.tmp
und versucht, eine Auswahl aus der Grepped-Eingabe zu lesen.
Mein Ansatz
Ich habe versucht, die -u
Flagge von zu verwenden read
, wie in
exec 4< /proc/$PPID/fd/0
exec 4> /proc/$PPID/fd/1
nl $INPUT >4
read -u4 -p"Select options: "
aber das macht nicht das, was ich mir erhofft hatte.
F: Wie erhalte ich die tatsächliche Benutzerinteraktion?
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; }'
was ziemlich gut funktioniert. Allerdings grep b foo | selector | wc -l
bricht hier rüber. Irgendwelche Ideen, wie man das behebt? Das, rangeselect
was ich verwendet habe, finden Sie übrigens unter pastebin.com/VAxTSSHs . Es ist ein einfaches AWK-Skript, das die Zeilen einer Datei druckt, die einem bestimmten Bereich von Leinenzahlen entsprechen. (Bereiche können Dinge wie "3-10, 12,14,16-20" sein.)
alias
das, sondern selector() { all of that stuff...; }
in eine Funktion. alias
Es benennt einfache Befehle um, während Funktionen einen zusammengesetzten Befehl in einen einzigen einfachen Befehl packen .