本部分内容参考自《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
命令以非零退出状态码退出。
评论区