Bash:屏蔽用户输入的密码,并带有*支持退格和特殊字符

问题描述

以下是我根据基于@SiegeX@mklement0来自this questionhere屏蔽密码输入的想法编写的代码段。

太好了,我唯一想要添加的就是只删除输入字符的长度,因此我们不会清除整行。

我对此不太了解,因此遇到了错误。

在下面输入“ 12345”并以空格隔开,数字不“退格”;没有错误。

输入“ 123FourFive”并后退空格会产生错误:line 9: [[: 123FourFiv: value too great for base (error token is "123FourFiv")

输入“ OneTwo345”并退格,似乎工作正常。

输入可能期望输入密码的符号,然后后退空格会产生错误:line 9: [[: OneTwo./?: syntax error: invalid arithmetic operator (error token is "./?")

在输入过程中还按箭头键会在退格后产生狂野的屏幕行为...

如何改善此情况,以便我们屏蔽用户输入,仅删除输入的内容?

还是我们在“重新发明轮子”?有没有其他东西可以做我正在尝试做的事情(这是屏蔽用户输入以在bash脚本中获取密码并将其放入变量)?

用户环境是带有Cinnamon的Linux Mint 19.3。

#!/bin/bash

printf "\n\tPlease enter password: "
    # mask the input for the password by @SiegeX and @mklement0 (https://stackoverflow.com/questions/4316730)
    while IFS= read -r -s -n1 char; do
        [[ -z "${char}" ]] && { printf '\n'; break; } # ENTER pressed; output \n and break.
        if [[ "${char}" == $'\x7f' ]]; then # backspace was pressed
            # @nooblag,only delete for length of entered chars?
            if [[ "${password}" -lt "${#password}" ]]; then printf '\b \b'; fi # erase one '*' to the left.
            [[ -n $password ]] && password=${password%?} # remove last char from output variable
        else
            # add typed char to output variable
            password+="${char}"
            # print '*' in its stead
            printf '*'
        fi
    done

printf "\tPassword: ${password}\n\n"

更新:askpass如建议的

enter image description here

几乎可以满足我的要求,但是如果用户尝试使用Ctrl + C放弃/杀死它,则会搞砸终端...

解决方法

这可能是解决方案!取自here

#!/bin/bash
#
# Read and echo a password,echoing responsive 'stars' for input characters
# Also handles: backspaces,deleted and ^U (kill-line) control-chars
#
unset PWORD
PWORD=
echo -n 'password: ' 1>&2
while true; do
  IFS= read -r -N1 -s char
  # Note a NULL will return a empty string
  # Convert users key press to hexadecimal character code
  code=$(printf '%02x' "'$char") # EOL (empty char) -> 00
  case "$code" in
  ''|0a|0d) break ;;   # Exit EOF,Linefeed or Return
  08|7f)  # backspace or delete
      if [ -n "$PWORD" ]; then
        PWORD="$( echo "$PWORD" | sed 's/.$//' )"
        echo -n $'\b \b' 1>&2
      fi
      ;;
  15) # ^U or kill line
      echo -n "$PWORD" | sed 's/./\cH \cH/g' >&2
      PWORD=''
      ;;
  [01]?) ;;                        # Ignore ALL other control characters
  *)  PWORD="$PWORD$char"
      echo -n '*' 1>&2
      ;;
  esac
done
echo
echo $PWORD

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...