D20
在Bash下可以采用内部命令read接收用户来自键盘的输入,并将输入的内容赋值给一个变量。
1. 基本的读取
语法:read [-p prompt] [variable1 variable2...]
-p选项用于在尝试读取任何输入之前显示prompt(提示信息)的内容到标准错误输出。一般使用这个选项提示用户输入哪些内容。
read命令每次从标准输入(或使用-u选项指定的文件描述符)中读取一行的内容,将第一个单词赋值给第一个变量variable1,第二个单词赋值给variable2,依次类推。如果输入的单词数少于指定的变量数,剩下的变量值设为空,环境变量IFS中的字符被作为分隔符来将输入的内容分隔为单词。
$ cat readUserInput_1.sh
#!/bin/bash
#202006
read -p "Enter your name: " username #提示输入用户名,并将输入内容赋值给变量
read -p "Enter your email address: " email
read -p "Are you sure to continue? [y/n]" input
case $input in
[yY]*)
echo "Name: $username"
echo "Email: $email"
;;
[nY]*)
exit
;;
*)
echo "Enter y or n, please."
exit
;;
esac
#执行
$ ./readUserInput_1.sh
Enter your name: Jessica
Enter your email address: a@b.com
Are you sure to continue? [y/n]y
Name: Jessica
Email: a@b.com
2. 输入超时
read命令的-t选项设置读取用户输入的超时时间。指定秒数内没有读入一整行的输入(即没有输入回车),read命令将超时并返回一个失败。
$ cat readUserInput_1.sh
#!/bin/bash
#202006
read -t 5 -p "Enter your name: " username #添加-t选项,超时未输入返回状态码142
read -t 5 -p "Enter your email address: " email
read -t 5 -p "Are you sure to continue? [y/n]" input
case $input in
[yY]*)
echo "Name: $username"
echo "Email: $email"
;;
[nY]*)
exit
;;
*)
echo "Enter y or n, please."
exit
;;
3. 隐藏方式读取
read命令的-s选项来隐藏用户的输入。指定-s选项,则来自终端的输入不会被显示出来。当脚本验证密码时是很有用的。
$ cat readPassword.sh
#!/bin/bash
#202006
password=''
echo -n "Enter password: "
while IFS= read -r -s -n1 char #使用-n隐式的从标准输入每次读取一个字符,且反斜杠不做转义字符处理,并将读取的字符赋值给char
do
if [ -z $char ] #如果char为空(即直接输出的回车),则退出while循环
then
echo
break
fi
if [[ $char == $'\x08' || $char == $'\x7f' ]] #如果输入的是退格键或删除键
then
[[ -n $paassword ]] && password=${password:0:${#password}-1} #从password中移除最后一个字符
printf '\b \b' #向左删除一个*
else #不是退格或删除键
password+=$char #将变量char追加到password
printf '*' #打印一个*
fi
done
echo "Password is: $password"
执行脚本:
$ ./readPassword.sh
Enter password: ***
Password is: abc
4. 从文件中读取
使用read命令从文件中读取数据的方法主要有两种:
1)在while或until循环中使用read命令,通过文件描述符一行一行的读取文件内容,后续介绍;
2)在for循环中使用cat <filename>来读取文件内容。
语法:
for data in $(cat filename)
do
command1
command2
...
commandN
done
注意:这里的data不是逐行,而是根据环境变量IFS的值作为分隔符来逐个单词的读取文件内容。可以通过修改IFS来实现按行读取。
$ cat readFromFilebyfor.sh
#!/bin/bash
#20200601
old_IFS=$IFS #保存原来的IFS
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` filename"
exit
fi
if [ ! -f $1 ]
then
echo "The file $1 does not exist!"
exit 1
fi
IFS=$'\n' #改为按行分隔
for line in $(cat $1) #逐行读取文件
do
echo $line
done
IFS=$old_IFS #恢复IFS
执行结果:
$ ./readFromFilebyfor.sh list.txt
ab dde
ab dde
abde
333
a
补充:如果按照默认的IFS,则:
$ cat readFromFilebyfor.sh
#!/bin/bash
#202006
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` filename"
exit
fi
if [ ! -f $1 ]
then
echo "The file $1 does not exist!"
exit 1
fi
for line in $(cat $1) #按照默认的IFS分隔读取单词
do
echo $line
done
执行结果:
$ ./readFromFilebyfor.sh list.txt
ab
dde
ab
dde
abde
333
a
注意:按照for循环结合IFS变量可以保留每行原有的格式,而while循环读取文件虽然方便,但会去掉重复的空格和制表符,即会消除每行的原有格式。请按需选择。
本节结束
欢迎大家评论交流,发现博文中存在的问题一定要留言哦