Общая проблема
Я хочу написать сценарий, который взаимодействует с пользователем, даже если он находится в середине цепочки каналов.
Конкретный пример
Конкретно, требуется file
или stdin
, отображает строки (с номерами строк), просит пользователя ввести выбор или номера строк, а затем печатает соответствующие строки stdout
. Давайте назовем этот скрипт selector
. Тогда в принципе, я хочу быть в состоянии сделать
grep abc foo | selector > myfile.tmp
Если foo
содержит
blabcbla
foo abc bar
quux
xyzzy abc
тогда selector
дарит мне (на терминале, а не в myfile.tmp
!) варианты
1) blabcbla
2) foo abc bar
3) xyzzy abc
Select options:
после чего я набираю
2-3
и в конечном итоге
foo abc bar
xyzzy abc
как содержание myfile.tmp
.
У меня есть скрипт выбора и работает, и в основном он работает отлично, если я не перенаправить ввод и вывод. Так
selector foo
ведет себя как я хочу. Однако при объединении вещей, как в приведенном выше примере, selector
печатает представленные параметры myfile.tmp
и пытается прочитать выборку из сброшенного ввода.
Мой подход
Я пытался использовать -u
флаг read
, как в
exec 4< /proc/$PPID/fd/0
exec 4> /proc/$PPID/fd/1
nl $INPUT >4
read -u4 -p"Select options: "
но это не то, что я надеялся.
Q: Как я могу получить реальное взаимодействие с пользователем?
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; }'
который работает довольно хорошо. Однако grep b foo | selector | wc -l
перерывы здесь. Есть идеи как это исправить? Кстати, то, rangeselect
что я использовал, можно найти на pastebin.com/VAxTSSHs . Это простой скрипт AWK, который печатает строки файла, соответствующие заданному диапазону номеров белья. (Диапазоны могут быть такими, как "3-10, 12,14,16-20".)
alias
, скорее selector() { all of that stuff...; }
в функцию. alias
es переименовывают простые команды, тогда как функции упаковывают составную команду в одну простую команду .