1. 命令行参数
向 shell 脚本传递数据的最基本方法是使用命令行参数。命令行参数允许在运行脚本时向命令行添加数据。
$ ./addem 10 30
本例向脚本 addem 传递了两个命令行参数(10 和 30)。
1.1 读取参数
bash shell 会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的所有参数。这也包括 shell 所执行的脚本名称。位置参数变量是标准的数字:$0 是程序名,$1是第一个参数,$2 是第二个参数,依次类推,直到第九个参数 $9。
使用单个命令行参数的简单例子
$ cat test1.sh#!/bin/bash# using one command line parameter#factorial=1for (( number = 1; number <= $1 ; number++ ))dofactorial=$[ $factorial * $number ]doneecho The factorial of $1 is $factorial$$ ./test1.sh 5The factorial of 5 is 120$
可以在 shell 脚本中像使用其他变量一样使用 $1 变量。shell 脚本会自动将命令行参数的值分配给变量,不需要你作任何处理。
如果需要输入更多的命令行参数,则每个参数都必须用空格分开。
$ cat test2.sh#!/bin/bash# testing two command line parameters#total=$[ $1 * $2 ]echo The first parameter is $1.echo The second parameter is $2.echo The total value is $total.$$ ./test2.sh 2 5The first parameter is 2.The second parameter is 5.The total value is 10.$
也可以在命令行上用文本字符串。
$ cat test3.sh#!/bin/bash# testing string parameters#echo Hello $1, glad to meet you.$$ ./test3.sh RichHello Rich, glad to meet you.$
记住,每个参数都是用空格分隔的,所以 shell 会将空格当成两个值的分隔符。要在参数值中
包含空格,必须要用引号(单引号或双引号均可)。
$ ./test3.sh 'Rich Blum'Hello Rich Blum, glad to meet you.$$ ./test3.sh "Rich Blum"Hello Rich Blum, glad to meet you.$
如果脚本需要的命令行参数不止 9 个,你仍然可以处理,但是需要稍微修改一下变量名。在
第 9 个变量之后,你必须在变量数字周围加上花括号,比如 ${10}。
$ cat test4.sh#!/bin/bash# handling lots of parameters#total=$[ ${10} * ${11} ]echo The tenth parameter is ${10}echo The eleventh parameter is ${11}echo The total is $total$$ ./test4.sh 1 2 3 4 5 6 7 8 9 10 11 12The tenth parameter is 10The eleventh parameter is 11The total is 110$
1.2 读取脚本名
可以用 $0 参数获取 shell 在命令行启动的脚本名。
$ cat test5.sh#!/bin/bash# Testing the $0 parameter#echo The zero parameter is set to: $0#$$ bash test5.shThe zero parameter is set to: test5.sh$
当传给 $0 变量的实际字符串不仅仅是脚本名,而是完整的脚本路径时,变量 $0 就会使用整个路径。
basename 命令会返回不包含路径的脚本名。
$ cat test5b.sh#!/bin/bash# Using basename with the $0 parameter#name=$(basename $0)echoecho The script name is: $name#$ bash /home/Christine/test5b.shThe script name is: test5b.sh$$ ./test5b.shThe script name is: test5b.sh$
2. 特殊参数变量
2.1 参数统计
特殊变量 $# 含有脚本运行时携带的命令行参数的个数。可以在脚本中任何地方使用这个特殊变量,就跟普通变量一样。
$ cat test8.sh#!/bin/bash# getting the number of parameters#echo There were $# parameters supplied.$$ ./test8.shThere were 0 parameters supplied.$$ ./test8.sh 1 2 3 4 5There were 5 parameters supplied.$$ ./test8.sh 1 2 3 4 5 6 7 8 9 10There were 10 parameters supplied.$$ ./test8.sh "Rich Blum"There were 1 parameters supplied.$
2.2 抓取所有的数据
$* 变量会将命令行上提供的所有参数当作一个单词保存。这个单词包含了命令行中出现的每一个参数值。基本上 $* 变量会将这些参数视为一个整体,而不是多个个体。
$@ 变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。
下面的例子给出了二者的差异。
$ cat test12.sh#!/bin/bash# testing $* and $@#echocount=1#for param in "$*"doecho "\$* Parameter #$count = $param"count=$[ $count + 1 ]done#echocount=1#for param in "$@"doecho "\$@ Parameter #$count = $param"count=$[ $count + 1 ]done$$ ./test12.sh rich barbara katie jessica$* Parameter #1 = rich barbara katie jessica$@ Parameter #1 = rich$@ Parameter #2 = barbara$@ Parameter #3 = katie$@ Parameter #4 = jessica$
$* 变量会将所有参数当成单个参数,而 $@ 变量会单独处理每个参数。
3. 移动变量
shift 命令会根据它们的相对位置来移动命令行参数。
在使用 shift 命令时,默认情况下它会将每个参数变量向左移动一个位置。所以,变量 $3 的值会移到 $2 中,变量 $2 的值会移到 $1中,而变量 $1 的值则会被删除(注意,变量 $0 的值,也就是程序名,不会改变)。
$ cat test13.sh#!/bin/bash# demonstrating the shift commandechocount=1while [ -n "$1" ]doecho "Parameter #$count = $1"count=$[ $count + 1 ]shiftdone$$ ./test13.sh rich barbara katie jessicaParameter #1 = richParameter #2 = barbaraParameter #3 = katieParameter #4 = jessica$
窍门 使用 shift 命令的时候要小心。如果某个参数被移出,它的值就被丢弃了,无法再恢复。也可以一次性移动多个位置,只需要给 shift 命令提供一个参数,指明要移动的位置数就行了。
$ cat test14.sh#!/bin/bash# demonstrating a multi-position shift#echoecho "The original parameters: $*"shift 2echo "Here's the new first parameter: $1"$$ ./test14.sh 1 2 3 4 5The original parameters: 1 2 3 4 5Here's the new first parameter: 3$
4. 处理选项
待补充
5. 获得用户输入
5.1 基本的读取
read 命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read 命令会将数据放进一个变量。
$ cat test21.sh#!/bin/bash# testing the read command#echo -n "Enter your name: "read nameecho "Hello $name, welcome to my program. "#$$ ./test21.shEnter your name: Rich BlumHello Rich Blum, welcome to my program.$
生成提示的 echo 命令使用了 -n 选项。该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据,而不是下一行。
实际上,read 命令包含了 -p 选项,允许你直接在 read 命令行指定提示符。
$ cat test22.sh#!/bin/bash# testing the read -p option#read -p "Please enter your age: " agedays=$[ $age * 365 ]echo "That makes you over $days days old! "#$$ ./test22.shPlease enter your age: 10That makes you over 3650 days old!$
read 命令会将姓和名保存在同一个变量中。read 命令会将提示符后输入的所有数据分配给单个变量,要么你就指定多个变量。输入的每个数据值都会分配给变量列表中的下一个变量。如果变量数量不够,剩下的数据就全部分配给最后一个变量。
$ cat test23.sh#!/bin/bash# entering multiple variables#read -p "Enter your name: " first lastecho "Checking data for $last, $first…"$$ ./test23.shEnter your name: Rich BlumChecking data for Blum, Rich...$
也可以在 read 命令行中不指定变量。如果是这样,read 命令会将它收到的任何数据都放进特殊环境变量 REPLY 中。
$ cat test24.sh#!/bin/bash# Testing the REPLY Environment variable#read -p "Enter your name: "echoecho Hello $REPLY, welcome to my program.#$$ ./test24.shEnter your name: ChristineHello Christine, welcome to my program.$
REPLY 环境变量会保存输入的所有数据,可以在 shell 脚本中像其他变量一样使用。
5.2 超时
-t 选项指定了 read 命令等待输入的秒数。当计时器过期后,read 命令会返回一个非零退出状态码。
$ cat test25.sh#!/bin/bash# timing the data entry#if read -t 5 -p "Please enter your name: " namethenecho "Hello $name, welcome to my script"elseechoecho "Sorry, too slow! "fi$$ ./test25.shPlease enter your name: RichHello Rich, welcome to my script$$ ./test25.shPlease enter your name:Sorry, too slow!$
5.3 隐藏方式读取
-s 选项可以避免在 read 命令中输入的数据出现在显示器上(实际上,数据会被显示,只是 read 命令会将文本颜色设成跟背景色一样)
$ cat test27.sh#!/bin/bash# hiding input data from the monitor#read -s -p "Enter your password: " passechoecho "Is your password really $pass? "$$ ./test27.shEnter your password:Is your password really T3st1ng?$
输入提示符输入的数据不会出现在屏幕上,但会赋给变量,以便在脚本中使用。
5.4 从文件中读取
也可以用 read 命令来读取 Linux 系统上文件里保存的数据。每次调用 read 命令,它都会从文件中读取一行文本。当文件中再没有内容时,read 命令会退出并返回非零退出状态码。
最常见的方法是对文件使用 cat 命令,将结果通过管道直接传给含有 read 命令的 while 命令。
$ cat test28.sh#!/bin/bash# reading data from a file#count=1cat test | while read linedoecho "Line $count: $line"count=$[ $count + 1]doneecho "Finished processing the file"$$ cat testThe quick brown dog jumps over the lazy fox.This is a test, this is only a test.O Romeo, Romeo! Wherefore art thou Romeo?$$ ./test28.shLine 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$