Ogólny problem
Chcę napisać skrypt, który wchodzi w interakcję z użytkownikiem, nawet jeśli jest on w środku łańcucha potoków.
Konkretny przykład
Konkretnie, zajmuje to file
lub stdin
wyświetla linie (z numerami linii), prosi użytkownika o wprowadzenie wyboru lub numerów linii, a następnie drukuje odpowiednie linie do stdout
. Nazwijmy ten skrypt selector
. Więc w zasadzie chcę być w stanie to zrobić
grep abc foo | selector > myfile.tmp
Jeśli foo
zawiera
blabcbla
foo abc bar
quux
xyzzy abc
następnie selector
przedstawia mi (na terminalu, nie w myfile.tmp
!) opcje
1) blabcbla
2) foo abc bar
3) xyzzy abc
Select options:
po czym piszę
2-3
i skończyć z
foo abc bar
xyzzy abc
jako zawartość myfile.tmp
.
Mam gotowy skrypt selektora i zasadniczo działa idealnie, jeśli nie przekierowuję danych wejściowych i wyjściowych. Więc
selector foo
zachowuje się tak, jak chcę. Jednak podczas przesyłania strumieniowego razem, jak w powyższym przykładzie, selector
drukuje przedstawione opcje myfile.tmp
i próbuje odczytać zaznaczenie z grepped input.
Moje podejście
Próbowałem użyć -u
flagi read
, jak w
exec 4< /proc/$PPID/fd/0
exec 4> /proc/$PPID/fd/1
nl $INPUT >4
read -u4 -p"Select options: "
ale to nie robi tego, na co liczyłem.
P: Jak uzyskać faktyczną interakcję użytkownika?
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; }'
który działa całkiem dobrze. Jednak grep b foo | selector | wc -l
tutaj się psuje. Wszelkie pomysły, jak to naprawić? Nawiasem mówiąc, to rangeselect
, którego użyłem, można znaleźć na pastebin.com/VAxTSSHs . Jest to prosty skrypt AWK, który drukuje wiersze pliku odpowiadające danemu zakresowi numerów bielizny. (Zakresy mogą być takie jak „3-10, 12,14,16-20”.)
alias
tego raczej selector() { all of that stuff...; }
w funkcji. alias
es zmienia nazwy prostych poleceń, podczas gdy funkcje pakują złożone polecenie w jedno proste polecenie .