首先来看一个例子:计算100以内所有奇数的和以及所有偶数的和;分别显示之;
[root@localhosttutor]# vim odd_even.sh
#!/bin/bash#EvenSum=0OddSum=0 for I in {1..100}; do if [ $[$I%2] -eq 0 ]; then EvenSum=$[$EvenSum+$I] else OddSum=$[$OddSum+$I] fidone echo "EvenSum is: $EvenSum. OddSumis: $OddSum."
[root@localhosttutor]# bash -n odd_even.sh
[root@localhosttutor]# bash odd_even.sh
EvenSum is: 2550. OddSum is:2500.
本例中计算的是100以内奇偶数的和,如果想要计算1000以内的奇偶数之和,那么就需要改动脚本中for循环语句的变量,如果要计算10000以内的奇偶数,同样也需要改动脚本,这样的做法即不利于脚本的维护,也不够便利。那么有没有一种更灵活的方法,让用户可以自行指定要计算的值呢?这里就引入了位置变量的概念。
位置变量可以看做传递给脚本的参数,如此例子中,当要执行odd_even.sh这个脚本时,可以传递一个参数作为for循环所使用的变量:bash odd_even.sh 100。这里100 可以替换成任意一个用户想使用的数字。而参数的个数也可以是任意的,根据参数所处的位置,可以用$1, $2,$3, $4...来表示。
下面来举例演示一下位置变量的使用方法:
例1. 显示用户传递的任意3个参数:
[root@localhosttutor]# vim pos.sh
#!/bin/bash#echo $1echo $2echo $3
[root@localhosttutor]# bash pos.sh ab cd ef
#这里传递了3个参数 ab, cd 和 efabcdef
[root@localhosttutor]# bash pos.sh ab cd ef gh
#如果传递了4个参数,但在脚本中只有3个位置变量,那么第4个参数将不会显示出来abcdef
除了用$1, $2, $3...表示位置参数外,$@、$*和$#这几个特殊变量也可以表示位置参数。
可以对目前接触的所有特殊变量进行一个总结:
$?:命令执行状态返回值
$@和$*: 引用所有的参数,但其中一个是将所有的参数分别显示,另一个则是将所有的参数当做一个整体的字符串来显示
$#:参数的个数
$#:参数的个数
修改上述脚本并执行,可以看出这几个特殊变量的用法:
[root@localhost tutor]# vim pos.sh
#!/bin/bash#echo $1echo $2echo $3echo $@echo $*echo $#
[root@localhost tutor]# bash pos.sh ab cd ef gh ij
abcdefab cd ef gh ijab cd ef gh ij5
例2. 传递一个用户名给脚本,来判断该用户是否存在
[root@localhosttutor]# vim if_user5.sh
#!/bin/bash# UserName=$1#这里$1即表示位置变量if id $UserName &>/dev/null; then echo "$UserName is Exists."else echo "$UserName is notExists."fi
[root@localhosttutor]# bash -n if_user5.sh
[root@localhosttutor]# chmod +x if_user5.sh
[root@localhosttutor]# bash -x if_user5.sh user1
#将 user1 传递给脚本,脚本会在$1的位置用user1进行替换+ UserName=user1+ id user1+ echo 'user1 is Exists.'user1 is Exists.
[root@localhosttutor]# bash -x if_user5.sh user2
+ UserName=user2+ id user2+ echo 'user2 is not Exists.'user2 is not Exists.
例3. 计算N以内所有奇数的和以及所有偶数的和;分别显示之;N是通过参数传递过来的正整数;
[root@localhosttutor]# vim even_odd1.sh
#!/bin/bash# EvenSum=0OddSum=0 for I in `seq 1 $1`; do if [ $[$I%2] -eq 1 ]; then OddSum=$[$OddSum+$I] else EvenSum=$[$EvenSum+$I] fidone echo "EvenSum:$EvenSum."echo "OddSum: $OddSum." echo "Sum:$[$EvenSum+$OddSum]"
[root@localhosttutor]# bash -n even_odd1.sh
[root@localhosttutor]# bash even_odd1.sh
#没有传递参数的情况EvenSum: 0.OddSum: 1.Sum: 1
[root@localhosttutor]# bash even_odd1.sh 100
EvenSum: 2550.OddSum: 2500.Sum: 5050
[root@localhosttutor]# bash even_odd1.sh 10000
EvenSum: 25005000.OddSum: 25000000.Sum: 50005000
如果无法预估由多少个参数传递到脚本中,可以使用循环来操作:
例4. 通过参数传递n个正整数给脚本,求其和
[root@localhosttutor]# vim uknow_para.sh
#!/bin/bash#Sum=0for I in $@; do#使用$@来表示引用所有的参数 Sum=$[$Sum+$I]done echo "Sum: $Sum."
[root@localhosttutor]# bash -n uknow_para.sh
[root@localhosttutor]# bash uknow_para.sh 1 2 3 4 5
Sum: 15.
在位置变量的使用中,可以使用shift [n]来排除已经使用过的参数,实现位置参数的轮替,看下面的例子
[root@localhosttutor]# vim shift.sh
#!/bin/bash#echo $1shiftecho $2shiftecho $3echo $4shift 2echo $5
[root@localhosttutor]# bash -n shift.sh
[root@localhosttutor]# bash shift.sh a b c d e
ace #可以看到shift会导致参数的跳跃引用
修改这个例子:
[root@localhosttutor]# vim shift.sh
#!/bin/bash#echo $1shiftecho $1shiftecho $1echo $2#连用时候就按数字顺序来shift 2#shift默认没有参数,但可以指定具体排除几个参数echo $1
[root@localhosttutor]# bash shift.sh a b c d e
abcde
灵活使用shift,可以在脚本中用一个$1来引用所有的参数, 如将例4中的$@改为$#:
[root@localhosttutor]# vim uknow_para1.sh
#!/bin/bash#Sum=0for I in `seq 0 $#`; do Sum=$[$Sum+$1] shiftdone echo "Sum: $Sum."
[root@localhosttutor]# vim uknow_para1.sh
[root@localhosttutor]# bash -n uknow_para1.sh
[root@localhosttutor]# bash uknow_para1.sh 1 2 3 4 5
uknow_para1.sh: line 5: 15+:syntax error: operand expected (error token is "+")#这里报错是因为没有第0个参数,而所有参数都被shift了之后,程序仍有一次循环Sum: 15.
为了避免报错,可以修改上述脚本:
[root@localhosttutor]# vim uknow_para1.sh
#!/bin/bash#Sum=0for I in `seq 1 $#`; do#将0 改为1 Sum=$[$Sum+$1] shiftdone echo "Sum: $Sum."
[root@localhosttutor]# bash uknow_para1.sh 1 2 3 4 5
Sum: 15.
[root@localhosttutor]# bash uknow_para1.sh 2 3 4 5 6
Sum: 20.
例5. 写一个脚本,完成以下要求:1、添加10个用户user1, user2, ..., user10;但要先判断用户是否存在,不存在而后再添加;2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;3、最后显示当前系统上共有多少个用户;
[root@localhosttutor]# vim useradd.sh
#!/bin/bash#Count=0 for I in {1..10}; do if id user$I &> /dev/null; then echo "user$I exists." else useradd user$I echo "Add user$Isuccessfully." Count=$[$Count+1]# Count是个计数器,用来统计添加的用户数 fidone echo "Add $Count newusers."echo "Total users: `wc -l/etc/passwd | cut -d' ' -f1`."
[root@localhosttutor]# bash -n useradd.sh
[root@localhosttutor]# bash useradd.sh
user1 exists.Add user2 successfully.Add user3 successfully.Add user4 successfully.Add user5 successfully.Add user6 successfully.Add user7 successfully.Add user8 successfully.Add user9 successfully.Add user10 successfully.Add 9 new users.Total users: 44.
[root@localhosttutor]# bash useradd.sh
user1 exists.user2 exists.user3 exists.user4 exists.user5 exists.user6 exists.user7 exists.user8 exists.user9 exists.user10 exists.Add 0 new users.Total users: 44.
例6. 对例5加以改进,完成以下要求:1、通过参数传递一系列用户名给脚本,让脚本添加这些用户;但要先判断用户是否存在,不存在而后再添加;2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;
[root@localhosttutor]# vim useradd1.sh
#!/bin/bash#Count=0 for UserName in $@; do if id $UserName &> /dev/null;then echo "$UserNameexists." else useradd $UserName echo "Add $UserNamesuccessfully." Count=$[$Count+1] fidone echo "Add $Count newusers."
[root@localhosttutor]# bash -n useradd1.sh
[root@localhosttutor]# bash useradd1.sh user1 user2 user3 hadoop iphone
user1 exists.user2 exists.user3 exists.Add hadoop successfully.Add iphone successfully.Add 2 new users.