使用`read`时如何启用向上/向下箭头键以显示先前的输入?

nac*_*cab 13 bash shell

我正在等待无限循环中的用户输入(使用'read')并希望有命令历史记录,即能够使用向上和向下箭头键显示已输入的先前输入,而不是获取^ [[A和^ [[B. 这可能吗?


感谢@ l0b0的回答.它让我朝着正确的方向前进.玩了一段时间后,我意识到我还需要以下两个功能,但我还没有设法得到它们:

  • 如果我按下并向上一个命令添加一些内容,我希望将整个内容保存在历史记录中,而不仅仅是添加内容.例

    $ ./up_and_down
    输入命令:hello
    ENTER
    输入命令:
    Up
    输入命令:hello you
    ENTER
    输入命令:
    Up
    输入命令:you
    (而不是"hello you")

  • 如果我不能继续上升因为我在历史数组的末尾,我不希望光标移动到前一行,而是希望它保持固定.

这是我到目前为止(up_and_down):

#!/usr/bin/env bash
set -o nounset -o errexit -o pipefail

read_history() {
    local char
    local string
    local esc=$'\e'
    local up=$'\e[A'
    local down=$'\e[B'
    local clear_line=$'\r\e[K'


    local history=()
    local -i history_index=0

    # Read one character at a time
    while IFS="" read -p "Enter command:" -n1 -s char ; do
        if [[ "$char" == "$esc" ]]; then 
            # Get the rest of the escape sequence (3 characters total)
            while read -n2 -s rest ; do
                char+="$rest"
                break
            done
        fi

        if [[ "$char" == "$up" && $history_index > 0 ]] ; then
            history_index+=-1
            echo -ne $clear_line${history[$history_index]}
        elif [[ "$char" == "$down" && $history_index < $((${#history[@]} - 1)) ]] ; then
            history_index+=1
            echo -ne $clear_line${history[$history_index]}
        elif [[ -z "$char" ]]; then # user pressed ENTER
            echo
            history+=( "$string" )
            string=
            history_index=${#history[@]}
        else
            echo -n "$char"
            string+="$char"
        fi
    done
}
read_history
Run Code Online (Sandbox Code Playgroud)

小智 17

使用命令-e选项read结合内置history命令的两个解决方案:

# version 1
while IFS="" read -r -e -d $'\n' -p 'input> ' line; do 
   echo "$line"
   history -s "$line"
done

# version 2
while IFS="" read -r -e -d $'\n' -p 'input> ' line; do 
   echo "$line"
   echo "$line" >> ~/.bash_history
   history -n
done
Run Code Online (Sandbox Code Playgroud)