читать с историей

11

Как сделать readисторию поддержки встроенных команд, нажимая клавиши вверх / вниз для их циклического переключения?

Я пытался поймать, когда вы нажимаете клавишу «вверх», но она не работает с read:

read -p '> ' -n 3 foo
echo
echo -n "$foo" | hexdump

Нажатие клавиш со стрелками, кажется, работает, и я могу обнаружить это, используя это, однако, если я нажму aa, это потерпит неудачу, так как будет считывать только первый символ идентификатора стрелки вверх, в то время как третий нужен для различения другой стрелки ключи.

Tyilo
источник

Ответы:

9

Вы можете использовать rlwrapдля этого, если вы не против установки программного обеспечения.

Возможно, вы захотите сохранить отдельный файл истории, в котором будет храниться история только для определенного приглашения в вашем скрипте (т.е. избегать смешивания с историей команд оболочки пользователя).

Вот пример, который может работать для вас:

#!/bin/sh
# Save in rlwrap_example.sh

HISTORY=$HOME/.myscript_history
USERINPUT=$(rlwrap -H $HISTORY sh -c 'read REPLY && echo $REPLY')
echo "User said $USERINPUT"

$ ./rlwrap_example.sh
hello
User said hello

В приведенном выше сценарии пользователь может использовать все функции чтения строки GNU , с историей, хранящейся в - и хранящейся в -  ~/.myscript_history. Твик по мере необходимости.

В качестве альтернативы вы можете использовать bash read -e, который включает readline для readвызовов, но вы, вероятно, обнаружите, что его функциональность истории слишком ограничена (т. Е. Почти отсутствует).

МРБ
источник
10

Чтобы скопировать замечательный ответ Майка Строяна из этого старого сообщения в списке рассылки :

Вы можете использовать «history -r» для чтения файла в историю оболочки и «history -s» для добавления каждой строки, которую вы прочитали, в историю. Затем используйте history -w, чтобы сохранить историю обратно в файл. Вот пример с редактированием readline в стиле vi.

#!/bin/bash
history -r script_history
set -o vi
CMD=""
while true
do
    echo "Type something"
    read -e CMD
    history -s "$CMD"
    echo "You typed $CMD"
    case "$CMD" in
        stop)
            break
            ;;
        history)
            history
            ;;
    esac
done
history -w script_history
echo stopping
Крис Пачехо
источник
Мне нравится это решение лучше, чем rlwrapпотому, что (по крайней мере, на моей машине) rlwrapне может корректно обрабатывать CTRL-C, например, попробуйте запустить USERINPUT=$(rlwrap -o cat)и нажать CTRL-C и посмотреть, как ваш терминал ведет себя впоследствии (выполните resetкоманду, чтобы вернуться в нормальное состояние снова) ,
zpon
Это работает очень хорошо, если вы не хотите устанавливать дополнительные библиотеки, и вы счастливы использовать отдельный файл для управления вводом.
Люк Экстон