How do I echo stars (*) when reading password with `read`?

此生再无相见时 提交于 2019-12-17 06:34:07

问题


What do I need to do for code in Bash, if I want to echo *s in place of password characters (or even just hide the characters completely) when the user types something in using read?


回答1:


As Mark Rushakoff pointed out, read -s will suppress the echoing of characters typed at the prompt. You can make use of that feature as part of this script to echo asterisks for each character typed:

#!/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"



回答2:


I really liked the answer that Wirone gave, but I didn't like that the backspacing would continue removing characters even back into the "Enter password: " prompt.

I also had some issues where pressing keys too rapidly would cause some of the characters to actually print on the screen... never a good thing when prompting for a password. =)

The following is my modified version of Wirone's answer which addresses these issues:

#!/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



回答3:


read -s should put it in silent mode:

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

See the read section in man bash.




回答4:


I would like to add something to Dennis Williamson's solution:

#!/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

In above example script handles backspace correctly.

Source




回答5:


I don't know about stars, but stty -echo is your friend:

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

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




回答6:


stty -echo
read something
stty echo

will stop user input being echoed to the screen for that read. Depending on what you are doing with prompts, you may want to add an extra echo command to generate a newline after the read.




回答7:


If you don't care about it being interactive, you can simply do

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

This will show a * for each character of the entered password after enter is pressed.




回答8:


I just made this Bash-specific function based on Dennis Williamson's, Wirone's and Logan VanCuren's answers:

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
}

It could be used like:

$ ask Username
Username: AzureDiamond
AzureDiamond

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

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



回答9:


#!/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 "-------------------------------"


来源:https://stackoverflow.com/questions/1923435/how-do-i-echo-stars-when-reading-password-with-read

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!