侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Shell脚本编程(11)之获取用户输入

zze
zze
2019-12-23 / 0 评论 / 0 点赞 / 671 阅读 / 4946 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

本部分内容参考自《Linux命令行与shell脚本编程大全 第3版》。

尽管命令行选项和参数是从脚本用户处获得输入的一种重要方式,但有时脚本的交互性还需要更强一些。比如你想要在脚本运行时问个问题,并等待运行脚本的人来回答。 bash shell 为此提供了 read 命令。

基本的读取

read 命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read 命令会将数据放进一个变量。下面是 read 命令的最简单用法。

$ cat test29.sh 
#!/bin/bash
echo -n "Enter your name: "
read name
echo "Hello $name, welcome to my program. "
$ ./test29.sh 
Enter your name: zhangsan
Hello zhangsan, welcome to my program. 

相当简单。注意,生成提示的 echo 命令使用了 -n 选项。该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据,而不是下一行。这让脚本看起来更像表单。
实际上, read 命令包含了 -p 选项,允许你直接在 read 命令行指定提示符。

$ cat test30.sh 
#!/bin/bash
read -p "Please enter your age: " age
days=$[ $age * 365 ]
echo "That makes you over $days days old! "
$ ./test30.sh 
Please enter your age: 22
That makes you over 8030 days old!

你会注意到,在第一个例子中当有名字输入时, read 命令会将姓和名保存在同一个变量中。read 命令会将提示符后输入的所有数据分配给单个变量,要么你就指定多个变量。输入的每个数据值都会分配给变量列表中的下一个变量。如果变量数量不够,剩下的数据就全部分配给最后一个变量。

$ cat test31.sh 
#!/bin/bash
read -p "Enter your name: " first last
echo "Checking data for $last, $first…"
$ ./test31.sh
Enter your name: zhangsan lisi
Checking data for lisi, zhangsan…

也可以在 read 命令行中不指定变量。如果是这样, read 命令会将它收到的任何数据都放进特殊环境变量 REPLY 中。

$ cat test32.sh 
#!/bin/bash
read -p "Enter your name: "
echo Hello $REPLY, welcome to my program.
$ ./test32.sh 
Enter your name: zhangsan
Hello zhangsan, welcome to my program.

REPLY 环境变量会保存输入的所有数据,可以在 shell 脚本中像其他变量一样使用。

超时

使用 read 命令时要当心。脚本很可能会一直苦等着脚本用户的输入。如果不管是否有数据输入,脚本都必须继续执行,你可以用 -t 选项来指定一个计时器。 -t 选项指定了 read 命令等待输入的秒数。当计时器过期后, read 命令会返回一个非零退出状态码。

$ cat test33.sh 
#!/bin/bash
if read -t 5 -p "Please enter your name: " name
then
	echo "Hello $name, welcome to my script"
else
	echo
	echo "Sorry, too slow! "
fi
$ ./test33.sh 
Please enter your name: 
Sorry, too slow! 

如果计时器过期, read 命令会以非零退出状态码退出,可以使用如 if-then 语句或 while 循环这种标准的结构化语句来理清所发生的具体情况。在本例中,计时器过期时, if 语句不成立,shell 会执行 else 部分的命令。
也可以不对输入过程计时,而是让 read 命令来统计输入的字符数。当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量。

$ cat test34.sh 
#########################################################################
# File Name: test34.sh
# Author:zze
# Mail:zhangzhongen326@gmail.com
# Create Time:2019-12-23 21:04:53
# Description: 
#########################################################################
#!/bin/bash
read -n1 -p "Do you want to continue [Y/N]? " answer
case $answer in
	Y | y) echo
		echo "fine, continue on…";;
	N | n) echo
		echo OK, goodbye
		exit;;
esac
echo "This is the end of the script"
$ ./test34.sh 
Do you want to continue [Y/N]? n
OK, goodbye

本例中将 -n 选项和值一起使用,告诉 read 命令在接受单个字符后退出。只要按下单个字符回答后, read 命令就会接受输入并将它传给变量,无需按回车键。

隐藏方式读取

有时你需要从脚本用户处得到输入,但又在屏幕上显示输入信息。其中典型的例子就是输入的密码,但除此之外还有很多其他需要隐藏的数据类型。
-s 选项可以避免在 read 命令中输入的数据出现在显示器上(实际上,数据会被显示,只是 read 命令会将文本颜色设成跟背景色一样)。这里有个在脚本中使用 -s 选项的例子。

$ cat test35.sh 
#!/bin/bash
read -s -p "Enter your password: " pass
echo
echo "Is your password really $pass? "
$ ./test35.sh 
Enter your password: 
Is your password really 123? 

输入提示符输入的数据不会出现在屏幕上,但会赋给变量,以便在脚本中使用。

从文件中读取

最后,也可以用 read 命令来读取 Linux 系统上文件里保存的数据。每次调用 read 命令,它都会从文件中读取一行文本。当文件中再没有内容时, read 命令会退出并返回非零退出状态码。
其中最难的部分是将文件中的数据传给 read 命令。最常见的方法是对文件使用 cat 命令,将结果通过管道直接传给含有 read 命令的 while 命令。下面的例子说明怎么处理。

$ cat test
The quick brown dog jumps over the lazy fox.
This is a test, this is only a test.
O Romeo, Romeo! Wherefore art thou Romeo?
$ cat test36.sh 
#!/bin/bash
count=1
cat test | while read line
do
	echo "Line $count: $line"
	count=$[ $count + 1]
done
echo "Finished processing the file"
$ ./test36.sh 
Line 1: The quick brown dog jumps over the lazy fox.
Line 2: This is a test, this is only a test.
Line 3: O Romeo, Romeo! Wherefore art thou Romeo?
Finished processing the file

while 循环会持续通过 read 命令处理文件中的行,直到 read 命令以非零退出状态码退出。

0

评论区