使用`read`读密码时如何回显星号(*)?

时间:2009-12-17 17:47:36

标签: bash shell passwords

当用户使用{{1}键入内容时,如果我想回复*代替密码字符(甚至只是完全隐藏字符),我需要对Bash中的代码做什么? }?

10 个答案:

答案 0 :(得分:56)

正如 Mark Rushakoff 所指出的那样,read -s将抑制在提示符下输入的字符的回显。您可以将此功能用作此脚本的一部分,以回显每个键入的字符的星号:

#!/bin/bash
unset password
prompt="Enter Password:"
while IFS= read -p "$prompt" -r -s -n 1 char
do
    if [[ $char == $'\0' ]]
    then
        break
    fi
    prompt='*'
    password+="$char"
done
echo
echo "Done. Password=$password"

答案 1 :(得分:18)

我真的很喜欢 Wirone 给出的答案,但我不喜欢退格会继续删除字符,甚至回到“输入密码:”提示符。

我也有一些问题,按键太快会导致一些字符实际打印在屏幕上......提示输入密码时从来都不是一件好事。 =)

以下是我修改后的 Wirone 的答案,解决了这些问题:

#!/bin/bash

unset PASSWORD
unset CHARCOUNT

echo -n "Enter password: "

stty -echo

CHARCOUNT=0
while IFS= read -p "$PROMPT" -r -s -n 1 CHAR
do
    # Enter - accept password
    if [[ $CHAR == $'\0' ]] ; then
        break
    fi
    # Backspace
    if [[ $CHAR == $'\177' ]] ; then
        if [ $CHARCOUNT -gt 0 ] ; then
            CHARCOUNT=$((CHARCOUNT-1))
            PROMPT=$'\b \b'
            PASSWORD="${PASSWORD%?}"
        else
            PROMPT=''
        fi
    else
        CHARCOUNT=$((CHARCOUNT+1))
        PROMPT='*'
        PASSWORD+="$CHAR"
    fi
done

stty echo

echo $PASSWORD

答案 2 :(得分:12)

read -s应该将其置于静音模式:

-s     Silent mode.  If input is coming from a terminal, characters are not echoed.

请参阅man bash中的read部分。

答案 3 :(得分:6)

我想在 Dennis Williamson 的解决方案中添加一些内容:

#!/bin/bash

unset password
echo -n "Enter password: "
while IFS= read -p "$prompt" -r -s -n 1 char
do
    # Enter - accept password
    if [[ $char == $'\0' ]] ; then
        break
    fi
    # Backspace
    if [[ $char == $'\177' ]] ; then
        prompt=$'\b \b'
        password="${password%?}"
    else
        prompt='*'
        password+="$char"
    fi
done

在上面的示例中,脚本正确处理退格。

Source

答案 4 :(得分:5)

我不知道明星,但stty -echo是你的朋友:

 #!/bin/sh 
 read -p "Username: " uname 
 stty -echo 
 read -p "Password: " passw; echo 
 stty echo

来源:http://www.peterbe.com/plog/passwords-with-bash

答案 5 :(得分:2)

stty -echo
read something
stty echo

将阻止用户输入回显到该读取的屏幕。根据您对提示的操作,您可能需要添加额外的echo命令以在读取后生成换行符。

答案 6 :(得分:2)

如果您不关心它是否具有互动性,您可以直接进行

read -s pass
echo "$pass" | sed 's/./*/g'

按下输入后,这将为输入密码的每个字符显示一个*。

答案 7 :(得分:1)

我刚刚根据 Dennis Williamson Wirone Logan VanCuren 的答案制作了这个特定于Bash的功能:< / p>

ask() {
  local 'args' 'char' 'charcount' 'prompt' 'reply' 'silent'

  # Basic arguments parsing
  while [[ "${1++}" ]]; do
    case "${1}" in
      ( '--silent' | '-s' )
        silent='yes'
        ;;
      ( '--' )
        args+=( "${@:2}" )
        break
        ;;
      ( * )
        args+=( "${1}" )
        ;;
    esac
    shift || break
  done

  if [[ "${silent}" == 'yes' ]]; then
    for prompt in "${args[@]}"; do
      charcount='0'
      prompt="${prompt}: "
      reply=''
      while IFS='' read -n '1' -p "${prompt}" -r -s 'char'; do
        case "${char}" in
          # Handles NULL
          ( $'\000' )
            break
            ;;
          # Handles BACKSPACE and DELETE
          ( $'\010' | $'\177' )
            if (( charcount > 0 )); then
              prompt=$'\b \b'
              reply="${reply%?}"
              (( charcount-- ))
            else
              prompt=''
            fi
            ;;
          ( * )
            prompt='*'
            reply+="${char}"
            (( charcount++ ))
            ;;
        esac
      done
      printf '\n' >&2
      printf '%s\n' "${reply}"
    done
  else
    for prompt in "${args[@]}"; do
      IFS='' read -p "${prompt}: " -r 'reply'
      printf '%s\n' "${reply}"
    done
  fi
}

可以像:

一样使用
$ ask Username
Username: AzureDiamond
AzureDiamond

$ ask -s Password
Password: *******
hunter2

$ ask First Second Third
First: foo
foo
Second: bar
bar
Third: baz
baz

答案 8 :(得分:0)

@nxnevanswer至少在macOS上对我没有作用。我做了一点简化,现在它是完美的:

#!/bin/bash

ask() {
    charcount='0'
    prompt="${1}: "
    reply=''
    while IFS='' read -n '1' -p "${prompt}" -r -s 'char'
    do
        case "${char}" in
            # Handles NULL
            ( $'\000' )
            break
            ;;
            # Handles BACKSPACE and DELETE
            ( $'\010' | $'\177' )
            if (( charcount > 0 )); then
                prompt=$'\b \b'
                reply="${reply%?}"
                (( charcount-- ))
            else
                prompt=''
            fi
            ;;
            ( * )
            prompt='*'
            reply+="${char}"
            (( charcount++ ))
            ;;
        esac
    done
    printf '\n' >&2
    printf '%s\n' "${reply}"
}

pwd="$(ask Password)"

echo "Your password is $pwd"

答案 9 :(得分:-1)

#!/bin/bash
echo "------------------------------"

n=7
echo " Enter Password :"

for (( i=1;i<n;i++ ))
do
    stty -echo
    read -r -s -n 1 char
    stty echo

    echo -n "*"
    pass+="$char"

done

echo " "
echo " Your password : $pass "

echo ""
echo "-------------------------------"