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


11

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

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

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

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

Ответы:


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

Это работает очень хорошо, если вы не хотите устанавливать дополнительные библиотеки, и вы счастливы использовать отдельный файл для управления вводом.
Люк Экстон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.