编辑3

编辑3

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 或其他一些捕获的字符不会被转换为字节值:

所有控制字符,除了:

  1. ^C (ASCII 03 ETX)
  2. ^J (ASCII 0A LF )
  3. ^M(ASCII 0D CR)
  4. ^Z(ASCII 1A SUB)
  5. ^\ (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"

相关内容