Как отобразить звездочки (*) при чтении пароля с помощью `read`? - PullRequest
37 голосов
/ 17 декабря 2009

Что мне нужно сделать для кода в Bash, если я хочу отобразить * s вместо символов пароля (или даже просто полностью скрыть символы), когда пользователь что-то вводит при использовании read?

Ответы [ 9 ]

56 голосов
/ 17 декабря 2009

Как отметил Марк Рушаков , 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"
18 голосов
/ 07 июля 2014

Мне очень понравился ответ, который дал 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
11 голосов
/ 17 декабря 2009

read -s следует перевести в беззвучный режим:

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

См. Раздел read в man bash.

6 голосов
/ 23 апреля 2014

Я хотел бы добавить что-то к решению Денниса Уильямсона :

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

В приведенном выше примере скрипт правильно обрабатывает backspace.

Источник

5 голосов
/ 17 декабря 2009

Я не знаю про звезды, но 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

2 голосов
/ 23 августа 2017

Если вас не интересует интерактивность, вы можете просто сделать

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

Это покажет * для каждого символа введенного пароля после нажатия Enter.

2 голосов
/ 17 декабря 2009
stty -echo
read something
stty echo

остановит ввод пользовательского ввода на экран для этого чтения. В зависимости от того, что вы делаете с приглашениями, вы можете добавить дополнительную команду echo для генерации новой строки после чтения.

1 голос
/ 05 января 2018

Я только что сделал эту специфическую для Bash функцию на основе Денниса Уильямсона *, 1002 *, Wirone и Logan VanCuren :

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
0 голосов
/ 24 марта 2014
#!/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 "-------------------------------"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...