在写安装程序免不了要输入密码一类的,c里比较直白,getchar()加printf()一想就可以了,具体的逻辑实现也不会多难。可是在shell这种限制性语言里可没那么简单了,比如你想下输入命令read,怎么能只读入一个字符就退出呢?
于是我上网搜了搜,改了改,感兴趣的不如一起来学习下。
stty cbreak -echo
if=/dev/tty bs=1 count=1 2> /dev/null
stty -cbreak echo
}
while : ; do
ret=`getchar`
case "$ret" in
^H) str=$(echo $str|sed 's/.$//')
echo -ne "\b \b"
;;
"") break;
;;
*) str="$str$ret"
echo -n "*"
esac
done
getchar()函数就仿c语言的自己做了一个,每次输入一个字符就退出。
具体的stty的设置可以自己man,这里第一行设置了“击一下键盘输入一个字符就会响应,而不是等到输入回车按行响应”。第三行恢复设置。第二行dd是个linux命令:
dd命令:
功能说明:读取,转换并输出数据。
语 法:dd [bs=<字节数>][cbs=<字节数>][conv=<关键字>][count=<区块数>][ibs=<字节数>][if=<文件>][obs=<字节数>][of=<文件>][seek=<区块数>][skip=<区块数>][--help][--version]
补充说明:dd可从标准输入或文件读取数据,依指定的格式来转换数据,再输出到文件,设备或标准输出。
参 数:
bs=<字节数> 将ibs( 输入)与obs(输出)设成指定的字节数。
cbs=<字节数> 转换时,每次只转换指定的字节数。
conv=<关键字> 指定文件转换的方式。
count=<区块数> 仅读取指定的区块数。
ibs=<字节数> 每次读取的字节数。
if=<文件> 从文件读取。
obs=<字节数> 每次输出的字节数。
of=<文件> 输出到文件。
seek=<区块数> 一开始输出时,跳过指定的区块数。
skip=<区块数> 一开始读取时,跳过指定的区块数。
--help 帮助。
--version 显示版本信息。
主程序包含了一个while循环来使你不断输入密码。
ret=`getchar` #取出输入的值放到ret变量里。这里你需要了解``和$()的意思。
然后根据ret的值来相应的处理:
^H代表backspace。为什么要对退格键进行特殊处理呢,你可以试一下,如果不特殊处理的话是不能发挥退格的功效的。为什么不能发挥退格的功效呢,那是因为此时处于raw mode下,而非cooked mode下。精彩的就在特殊处理的部分,需要清楚的是所谓的特殊处理就是“删除输入backspace代表的字符(在raw模式下backpace键输入的是^H),删除一个*号” echo $str|sed 's/.$// $代表最后一行,echo $str最后一行就是换行。.$就是倒数第二行最后一个字符(即str最后一个字符^H)。。替换成空就完成了“删除输入backspace代表的字符”,然后在echo "\b"删除一个*号就OK了。。。
在此不得不感叹一下linux下这些命令功能的强大,聊聊两句想实现什么功能实现什么功能,再感叹设计者的强大。
然后输入为空(回车)时退出循环,其他情况都是密码显示*号。