首先来看一个例子:计算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.