按Enter仍然执行其分隔符工作,但read
命令只是安静地结束,避免扰乱控制台滚动。基本上,aread -s
只影响端线。
答案1
n1
如果读取字符是输入,则知道 read 将读取变量(带有选项)设置为空值,您可以执行以下操作:
#!/bin/bash
while IFS= read -srn1 a ;do
[[ "${a+x$a}" = "x" ]] && break
var=$var$(printf '%s' "$a")
printf '%s' "$a"
done
printf '\n%s\n' "$var"
请注意,由 stty 或其他一些捕获的字符不会被转换为字节值:
所有控制字符,除了:
- ^C (ASCII 03 ETX)
- ^J (ASCII 0A LF )
- ^M(ASCII 0D CR)
- ^Z(ASCII 1A SUB)
- ^\ (ASCII 1C FS )
要真正“查看”前一个字符上的退格字符,请添加此循环以 print var (就在上面的代码之后):
echo
while IFS= read -srn1 a; do
printf '%s' "$a"
sleep 0.5
done <<<"$var"
编辑3
要让退格键删除一个字符,而不捕获该字符并打印修改后的字符串,请尝试以下操作:
#!/bin/bash
while IFS= read -srn1 a ;do
[[ "${a+x$a}" = "x" ]] && break
if [[ $a = $'\x7f' || $a = $'\x08' ]]; then
var=${var%?}
[[ $a = $'\x7f' ]] && printf '\x0d%s \x08' "$var"
[[ $a = $'\x08' ]] && printf '\x0d%s ' "$var"
else
var=$var$(printf '%s' "$a")
fi
printf '%s' "$a"
done
printf '\n%s\n' "$var"
printf '%s' "$var" | od -An -tx1
while IFS= read -srn1 a; do
printf '%s' "$a"
sleep 0.5
done <<<"$var"
答案2
您可以调用 zsh 的行编辑器(它是完全可配置的,并且通常有更多功能)先进的比 readline (bash 可以用read -e
)调用),例如:
var=$(
saved_tty=$(stty -g)
var=default-value zsh -c '
zle-line-finish() { # hook run upon leaving the line editor (zle)
CURSOR=$#BUFFER # move the cursor to the end
zle -R # force a redraw of the editor
printf %s $BUFFER # output value on stdout
kill $$ # kill ourself to prevent zle cleanup
}
zle -N zle-line-finish
vared -p "Text before [" var'
# we need to restore the tty settings by ourselves, as we prevented zsh
# from doing so when killing it:
stty "$saved_tty"
)
printf '] Text after\n'
printf 'var = "%s"\n' "$var"
运行后,给出:
Text before [value edited] Text after
var = "value edited"
虽然bash
现在允许您将键绑定到 shell 代码小部件,但它会在执行小部件之前清除当前行的内容,因此您必须在处理程序上重新绘制提示和值Return:
var=$(prompt="Text before [" var=default-value bash -c '
bind -x '\''"\r":printf >&2 %s "$prompt$READLINE_LINE"; printf %s "$READLINE_LINE"; exit'\'' 2> /dev/null
IFS= read -rep "$prompt" -i default-value')
printf '] Text after\n'
printf 'var = "%s"\n' "$var"