ユーザーがread
を使用して何かを入力したときに、パスワード文字の代わりに*
sをエコーする(または単に文字を完全に非表示にする)場合、Bashのコードに対して何をする必要がありますか?
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"
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
read -s
はサイレントモードにする必要があります。
-s Silent mode. If input is coming from a terminal, characters are not echoed.
man bash
のread
セクションを参照してください。
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
上記の例では、スクリプトはバックスペースを正しく処理します。
星については知りませんが、stty -echoはあなたの友達です:
#!/bin/sh
read -p "Username: " uname
stty -echo
read -p "Password: " passw; echo
stty echo
インタラクティブであることを気にしない場合は、単に行うことができます
read -s pass
echo "$pass" | sed 's/./*/g'
これは、入力が押された後、入力されたパスワードの各文字に対して*を表示します。
stty -echo
read something
stty echo
その読み取りのために画面にエコーされるユーザー入力を停止します。プロンプトで何をしているのかに応じて、読み取り後に改行を生成するために、余分なecho
コマンドを追加することができます。
Dennis Williamson 's、Wirone' s、およびLogan VanCurenの回答に基づいて、このBash固有の関数を作成しました。
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