有时我们需要写个和运行脚本的人交互的脚本。bash shell提供了一些不同的方法来从用户处获得数据,包括命令行参数(添加在命令后的数据值)、命令行选项(可修改命令行为的单字母值)以及直接从键盘读取输入的能力。
一、命令行参数
向shell脚本传数据的最基本方法是使用命令行参数。命令行参数允许在运行脚本时向命令行添加数据值:
$ ./addem 10 30 #向脚本addem传递了两个命令行参数
1.1 读取参数
bash shell会将一些称为位置参数的特殊变量分配给命令行输入的所有参数。位置参数变量是标准的数字:$0
是程序名,$1
是第一个参数,$2
是第二个参数,以此类推,直到第9个参数$9
.
命令行参数可以是数值,也可以是文本字符串。当输入的是字符串包含空格时,需要用引号包住(shell会将空格当成分割两个值的分隔符,用单引号和双引号都可以)。将文本字符串作为参数传递时,引号并不是数据的一部分。它们只是将数据的开始和结尾和其他内容分开。
如果脚本需要多于9个命令行参数,需要修改一下变量名。在第9个变量之后,必须在变量数字周围加花括号,比如${10}。
1.2 读取程序名
可以用$0来获取shell在命令行启动的程序的名字。
$cat test2
#!/bin/bash
#testing the $0 parameter
echo The command entered is: $0
$
$./test2
The command entered is: ./test2
$
$/home/rich/test2
The command entered is: /home/rich/test2
这就会出现一个小问题,当传给$0变量的真实字符串是整个脚本的路径时,程序中就会使用整个路径,而不仅仅是程序名。
如果我们希望去掉命令行下运行脚本的任何路径,我们可以用basename命令,它只返回程序名而不包括路径。
$cat test3
#!/bin/bash
name=`basename $0`
echo The command entered is: $name
$
$./test3
The command entered is:test3
$
$/home/rich/test3
The command entered is:test3
$
1.3 测试参数
在shell脚本中使用命令行参数要小心,如果脚本不加参数运行,可能会出问题。所以在使用前检查数据确实已经存在于变量很有必要。
$cat test4
#!/bin/bash
if[-n "$1"] #使用-n参数来检查命令行参数中是否有数据
then
echo Hello $1, glad to meet you.
else
echo "sorry, you did not identify yourself."
fi
$
二、特殊参数变量
2.1 参数计数
$#
变量含有参数的总数值。
所以在脚本中可以判断$#
的值是不是符合要求。
那么${$#}
是不是代表最后一个命令行参数变量呢?实际上并不是。我们应该用${!#}
来表示。
$cat test5
#!/bin/bash
params=$#
echo The last parameter is $params
echo The last parameter is ${!#}
$
$ ./test5 1 2 3
The last parameter is 3
The last parameter is 3
$
$ ./test5
The last parameter is 0
The last parameter is ./test5
上面的例子可以看出,当存在命令行参数的时候两种表示的方式的结果相同。当命令行上没有参数时,$#
的值为0,在params变量中也为0,但${!#}
变量会返回命令行用到的脚本名。
2.2 抓取所有的数据
有些时候,你希望获取命令行上的所有参数然后遍历它们。这时候可以不需要用$#
先判断有多少参数然后再遍历它们。$*
和$@
变量提供了对所有参数的快速访问。这两个都能够在单个变来那个中存储所有的命令行参数。
$*
变量会将命令行上提供的所有参数当作单个单词保存,每个词是指命令行上出现的每个值。基本上,$*
变量会将这些都当作一个参数,而不是多个对象。
$@
变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词,它允许你遍历所有的值,将提供的每个参数分割开来,这通常通过for命令完成。
$cat test6
#!/bin/bash
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
$
$ ./test6 rich barbara katie jessica
$* paramter #1 = rich barbara katie jessica
$@ paramter #1 = rich
$@ paramter #2 = barbara
$@ paramter #3 = katie
$@ paramter #4 = jessica
总结:$*
变量会将所有参数当成单个参数,而$@
变量会单独处理每个参数。
三、移动变量
bash shell提供了shift命令来帮助操作命令行参数。shift命令回去根据它们的相对位置来移动命令行参数。
使用shift命令时,默认情况下它会将每个参数变量减一。所以,变量 3的值会移到 2,变量 2的值会移到 1,而变量 1的值则会被删除。注意:变量 0的值也就是程序名不会改变。
所以遍历命令行参数的另一个方法是只操作第一个参数,移动参数,然后继续操作第一个参数。
$cat test7
#!/bin/bash
count=1
while [ -n "$1"]
do
echo "parameter #$count = $1"
count=$[$count+1]
shift
done
$
$ ./test7 rich barbara katie jessica
$@ paramter #1 = rich
$@ paramter #2 = barbara
$@ paramter #3 = katie
$@ paramter #4 = jessica
使用shift命令时要小心。当一个参数被移除后,它的值会被丢掉并且无法恢复。