关键词: 使用命令行参数, 设置选项 和 获取用户输入
- 命令行参数
向 shell 脚本传递数据的最结伴方式是使用 命令行参数(command line parameters). 使用命令行参数可以在执行脚本时向命令行中添加数据值: ./addem 10 30
这个例子向脚本 addem 传递了两个命令行参数(10 和 30).脚本将使用特殊变量来处理命令行参数.下面几节将介绍在 bash shell 脚本中如何使用命令行参数.
1) 读取参数
bash shell 将在命令行中输入的所有参数赋值给一些特殊变量, 这些变量称为 位置参数(positional parameter). 其中还包括 shell 执行的程序的名称. 位置参数通过标准数字表示, 其中 $0 为程序名称, $1 为第一个参数, $2 为第二个参数, 以此类推, 直到 $9 为第九个参数.
#!/bin/bash
# using one command line parameter
factorial=1
for (( number =1; number <= $1 ; number++ ))
do
factorial=$[ $factorial * $number ]
done
echo The factorial of $1 is $factorial
# 运行: ./test1 5
# 可以在 shell 脚本中像使用其他变量一样使用变量 $1. shell 脚本自动将命令行参数赋值给变量$1.无需用户干预.
如果需要输入更多命令行参数, name必须在命令行中使用空格分隔每个参数.
#!/bin/bash
#testing two command line parameters
total=$[ $1 * $2 ]
echo The first paramerer is $1.
echo The second parameter is $2.
echo The total value is $total.
# 运行: ./test2 2 5
也可以在命令行中使用文本字符串
#!/bin/bash #testing string parameters echo Hello $1, glad to meet you.
# 运行: ./test3 root
# 输出: Hello root, glad to meet you.
shell 将在命令行中输入的字符串传递给脚本. 但是如果要传递一个包含空格的文本字符串, 则会出现问题.
# ./test3 root blum
# Hello root, glad to meet you.
每个参数都是空格分隔的, 所以 shell 会将空格解析为两个值的分隔标志.要想在参数值中包含空格, 就必须使用引号(单引号和双引号均可). 引号不作为数据的一部分, 他们只是界定数据的起始和结束
# ./test3 'root Blum' # Hello root Blum, glad to meet you. # ./test3 "root Blum" # Hello root Blum, glad to meet you.
如果脚本需要的命令行参数多余9个, name可以连续在命令行中添加命令行参数, 但是变量名称会稍有变化. 在第9个变量之后, 必须使用大括号将变量括起来,如${10}
#!/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
2) 读取程序名称
使用参数 $0 可以确定 shell 从命令行启动的程序的名称. 在编写具有多个功能的工具时, 这种方法非常方便. 但是, 也有可能会遇到一些小问题
#!/bin/bash # testing the $0 parameter echo The command entered is: $0 # 运行: ./test5 # 输出: The command entered is: ./test5 # 运行: /home/test5 # 输出: The command entered is: /home/test5
传递给变量 $0 的字符串实际上是程序的完整路径, 而不仅仅是程序的名称. 如果希望编写的脚本能够根据通过命令运行的脚本的名称执行不同功能, 必须进行一些额外的处理. 需要去除通过命令行运行脚本时使用的所有路径.
basename 命令只返回程序名称, 不带路径
#!/bin/bash # using basename with the $0 parameter name=`basename $0` echo The command entered is: $name # 运行: ./test5b # 输出: The command entered is: test5b # 运行: /home/test5b # 输出: The command entered is: test5b
基于使用的脚本的名称来执行不同功能的脚本
#!/bin/bash # testing a multi-function script name=`basename $0` if [ $name = "addem" ] then total=$[ $1 + $2 ] elif [ $name = "multem" ] then total=$[ $1 * $2 ] fi echo The calculated value is $total
# 运行: ./addem 2 5
# 输出: The calculated value is 7
# 运行: ./multem 2 5
# 输出: The valculated value is 10
3) 测试参数
当脚本认为参数变量中包含数据, 但实际上其中并没有数据时, 极有可能会生成脚本错误消息.这种编写脚本方法很不好.
#!/bin/bash # testing parameters before use if [ -n "$1" ] then echo Hello $1, glad to meet you. else echo "Sorry, you didn't identify yourself." fi # 运行: ./test7 root # 输出: Hello root, glad to meet you. # 运行: ./test7 # 输出: Sorry, you didn't identity yourself.
- 特殊的参数变量
在 bash shell 中有一些特殊的变量用于跟踪命令行参数.
1) 参数技术
特殊变量 $# 中存储执行脚本时包含的命令行参数的个数. 在脚本中的任意位置都可以使用这个特殊变量, 就像使用普通变量一样
#!/bin/bash # getting the number of parameters echo There were $# parameters supplied # 运行: ./test8 # 输出: There were 0 parameters supplied. # 运行: ./test8 1 2 3 4 5 # 输出: There were 5 parameters supplied # 运行: ./test8 1 2 3 4 5 6 7 8 9 10 # 输出: There were 10 parameters supplied.
使用参数测试现有的参数个数
#!/bin/bash # testing parameters if [ $# -ne 2 ] then echo Usage: test9 a b else total=$[ $1 + $2 ] echo The total is $total fi # 运行: ./test9 # 输出: Usage:test9 a b # 运行: ./test9 10 # 输出: Usage: test a b # 运行: ./test9 10 15 # 输出: The total is 25 # 运行: ./test9 10 15 20 # 输出: Usage: test9 a b
上面的 if-then 语句使用 test 命令对命令行中提供的参数个数执行一个数值测试. 如果提供的参数个数不正确, 可以打印一个表示脚本的正确使用方式的错误信息.
这个变量还提供了一个获取 命令行中最后一个参数的方法
#!/bin/bash # testing grabbing last parameter echo The last parameter was ${$#} # 运行: ./badtest1 10 # 输出: The last parameter was 15354 # 问题: 输出值并非想要的值, 结果表明不能再大括号中使用美元符号 # 解决: 必须将美元符号替换为感叹号 #!/bin/bash # grabbing the last parameter params=$# echo The last parameter is $params echo The last paramerer is ${!#} # 运行: ./test10 1 2 3 4 5 # 输出: The last parameter is 5 ; The last parameter is 5 # 运行: ./test10 # 输出: The last parameter is 0 ; The last parameter is ./test10
可以将 $# 变量赋值给变量 params, 然后按照特殊命令行参数变量的格式使用变量 params. $# 与 params 这两种方式都有效. 当命令行没有任何参数时, $# 的值为零, 变量 params 的值也为零, 但变量 #{!#} 将返回命令行中使用的脚本的名称.
2) 获取所有数据
变量 $* 和 $@ 为获取所有参数提供了服务. 这两个变量都是在一个变量中包含所有的命令行参数
变量 $* 将命令行中提供的所有参数作为一个单词处理. 这个单词中包含出现在命令行中的每一个参数值. 本质上, 变量 $* 不是将参数视为多个对象, 而是将他们看作一个参数.
而另一方面, 变量 $@ 将命令行中提供的所有参数作为同一个字符串中的多个单词处理. 允许对其中的值进行迭代, 分隔开锁提供的不同参数, 通常使用 for 命令来进行这样的迭代.
#!/bin/bash # testing $* and $@ echo "Using the $* method: $*" echo "Using the $@ method: $@" # 运行: ./test11 rich barbara katie jessica # 输出: Using the $* method: rich barbara katie jessica ; Using the $@ method: rich barbara katie jessica
表面看来, 两个变量生成相同的输入, 一次显示提供的所有命令行参数
#!/bin/bash # testing $* and $@ count=1 for param in "$*" do echo "$* Parameter #$count = $param" count=$[ $count + 1 ] done count=1 for param in "$@@" do echo "$@ Parameter #$count = $param" count=$[ $count + 1 ] done # 运行: ./test12 a b c # 输出: # $* Parameter #1 = a b c # $@ Parameter #1 = a # $@ Parameter #2 = b # $@ Parameter #3 = c
通过使用 for 命令迭代特殊变量, 可以看懂这两个变量处理命令行参数的区别. 变量 $* 将所有参数视为一个单词, 而变量 $@ 分别对待每个参数.
3) 移位