我正在等待无限循环中的用户输入(使用'read')并希望拥有命令历史记录,即能够使用向上和向下箭头键显示已输入的先前输入获得^ [[A和^ [[B.这可能吗?
感谢@ l0b0的回答。它让我朝着正确的方向前进。玩了一段时间后,我意识到我还需要以下两个功能,但我还没有设法得到它们:
如果我按下并向上一个命令添加内容,我希望将整个内容保存在历史记录中,而不仅仅是添加内容。实施例
$ ./up_and_down
输入命令:hello
输入
输入命令:
向上
输入命令:你好
输入
输入命令:
向上
输入命令:你
(而不是“你好”)
如果我不能继续上去因为我在历史数组的末尾,我不希望光标移动到上一行,而是希望它保持固定。
这是我到目前为止(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
答案 0 :(得分: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
答案 1 :(得分:2)
我使用rlwrap在不支持它的程序中启用readline功能。也许你可以试试这个。 rlwrap代表readline包装器。此命令拦截您的密钥并按下键并替换提示whit先前的命令。
sintax只是rlwrap ./your-script
。
答案 2 :(得分:2)
对读取命令使用-e
选项(并确保readline
配置为使用向上/向下箭头键循环执行命令历史记录。)
help read | less -p '-e'
答案 3 :(得分:2)
有趣的问题 - 这是迄今为止的结果:
#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
read_history() {
local char=
local string=
local -a history=( )
local -i histindex=0
# Read one character at a time
while IFS= read -r -n 1 -s char
do
if [ "$char" == $'\x1b' ] # \x1b is the start of an escape sequence
then
# Get the rest of the escape sequence (3 characters total)
while IFS= read -r -n 2 -s rest
do
char+="$rest"
break
done
fi
if [ "$char" == $'\x1b[A' ]
then
# Up
if [ $histindex -gt 0 ]
then
histindex+=-1
echo -ne "\r\033[K${history[$histindex]}"
fi
elif [ "$char" == $'\x1b[B' ]
then
# Down
if [ $histindex -lt $((${#history[@]} - 1)) ]
then
histindex+=1
echo -ne "\r\033[K${history[$histindex]}"
fi
elif [ -z "$char" ]
then
# Newline
echo
history+=( "$string" )
string=
histindex=${#history[@]}
else
echo -n "$char"
string+="$char"
fi
done
}
read_history
答案 4 :(得分:0)
据我所知,没有。 “up”和“down”都是和任何一个一样好的符号(就此而言,Cp和Cn在bash中的功能上与“up”和“down”相同),并且可以作为你的''的一部分输入重新尝试阅读。
也就是说,假设你的意思是bash内置read
。您可以查看联机帮助页以获取任何选项,但我想不出任何可以做您想做的黑客攻击,至少现在不行......
-n 1
上设置read
,然后检查您是否只是阅读“向上”或“向下”并使用{{1}来完成获取所需的命令。您可能需要创建一个局部变量来计算“向上”和“向下”,然后从history
获取具有适当偏移量的相关命令,将其输出到屏幕&amp;如果下一个history
返回一个空字符串,请使用找到的命令。
正如我所说,不能测试这个atm,也不知道它是否会起作用。