一、条件测试方式:
bash命令
[ expression ] 一个中括号,其中内容为命令,括号两端必须要有空格
[[ expression ]] 两个中括号,其中内容为关键字,括号两端必须要有空格
test expression
组合测试条件:
与:-a
或:-o
非:!
通常用在[ ],或` `中
————————————————————
bash命令组合测试:
与:&&
或:||
非:!
二、整数测试:
expression:$A 比较符号 $B
大于或等于:-ge 例如:$A –ge $B
小于或等于:-le
等于:-eq
不等:-ne
大于:-gt
小于:-le
三、字符测试:
>:大于
>:小雨
==:等于 #注意一个=是赋值,赋值时,等号两边也不要空格,A=B,A = B是不同的两个概念
!=:不等于
=~:判断左边的字符串是否能够被右边的模式所匹配;通常用于` `;例如[[ $opt =~ $opt ]]
单目操作
-z $A:为空则为真,不空则为假
-n $A:为空则为假,不空则为真
四、文件测试
操作符 文件路径
-f: 测试其是否为普通文件,即ls -l时文件类型为-的文件
-d: 测试其是否为目录文件,即ls -l时文件类型为d的文件
-e: 测试文件是否存在;存在为真,否则为假
-r: 测试文件对当前用户来说是否可读
-w: 测试文件对当前用户来说是否可写
-x: 测试文件对当前用户来说是否可执行
-s: 测试文件大小是否不空,不空则真,空则假
例:如果/tmp/test10不存在,就创建之
if [ ! -e /tmp/test10 ]; then
mkdir /tmp/test10
fi
五、bash变量类型
局部变量
本地变量
环境变量
位置变量
特殊变量:
$?:用于保存刚刚执行的命令的状态返回值;
0:成功执行;
1-255:表示执行失败,1、2、127这3个返回值默认被系统占用,可以使用exit命令在脚本中自定义脚本执行状态返回值;如果不定义,脚本执行状态返回值取决于脚本执行结束前最后执行的那个语句的状态;
$* ,$@ 引用所有参数;
$#:位置参数的个数;
$0:脚本名称;
六、if语法
(1)单分支if语句:
if 条件; then
语句1
语句2
······
fi
#意为如果条件满足,则执行语句1,2,······
(2)双分支if语句:
if 条件; then
语句1
语句2
······
else
语句3
语句4
······
fi
#意为如果条件满足就执行语句1,2,······,否则执行语句3,4,······
(3)多分支if语句:
if 条件1; then
语句1
语句2
······
elif 条件2; then
语句3
语句4
······
elif 条件3; then
语句5
语句6
······
else
语句7
语句8
······
fi
#意为如果条件1满足就执行语句1,2,······,否测试条件2,如果满足就执行语句3,语句4,······,否则测试条件3······
七、语法运用示例
练习1:如果用户存在,就说明其存在,如不存在也需说明(此处用了命令id,还可以使用grep匹配来判断用户是否存在)
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if id $1 &> /dev/null; then #$1是传递给shell脚本的第一个参数 echo "$1 exists." else echo "$1 is not exists." fi
#运行脚本时,后接参数root,youshine,ehhe就是通过$1传递给脚本的
练习中的/dev/null,是黑洞,当我们不需要命令返回信息时,即可指向它。
if语句中通过命令执行的状态返回值(可以在当前命令执行后,echo $?查看)进行判断,
0表示成功执行,1-255表示执行失败,一般linux系统已经占用了1、2、127,所以当我们自己写脚本时,可以使用exit命令,自定义脚本执行状态的返回值,如果不定义,状态返回值取决于脚本最后一条命令的状态返回值。
练习2:如果用存在,就显示其UID和SHELL,否则告知不存在
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 UserName=$1 #在底下引用$1,没有用,就把$1赋值给UserName了 if id $1 &> /dev/null;then echo "$1 is exists." echo "UID:`grep "^$UserName:" /etc/passwd | cut -d: -f3`" echo "SHELL:`grep "^$UserName:" /etc/passwd | cut -d: -f7`" else echo "$1 is not exists." fi
练习3:如果文件中有空白行,就显示其空白行数,没有则告知(给参数时,需要指明文件路径,例如/etc/rc.d/rc,sysinit)
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 FileName=$1 if grep "^$" $1 &> /dev/null; then echo "The file have space line." echo "SPACE LINE:`grep "^$" $FileName | wc -l`" else echo "The file have no space line." fi
练习4:写一个脚本,生成两个随机数,比较其大小;显示大数(bash 内置变量$RANDOM,用于生成随机数)
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 A=$RANDOM B=$RANDOM if [ $A -gt $B ];then #注意括号中的空格 echo "Max number is $A." else echo "Max number is $B." fi
练习5:写一脚本,随机生成一个整数,判定,显示其奇偶性
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 A=$RANDOM if [ $[$A%2] -eq 0 ]; then #这里用%取除以2取余 echo "$A is Even." else echo "$A is Odd." fi
练习6:给定一个用户,如果其ID号大于499,就说明其是普通用户,否则,就说明其是管理员或系统用户
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 UserName=$1 Uid=grep "^$UserName:" /etc/passwd | cut -d: -f3` #此处注意变量不要使用UID,会报./usertype.sh: line 7: UID: readonly variable的错误 if [ $Uid -gt 499 ]; then echo "$1 is a common user." else echo "$1 is a administrator or system user." fi #或者
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 UserName=daemon Uid=`id -u $UserName` if [ $Uid -gt 499 ]; then echo "A common user: $UserName." else echo "admin user or system user: $UserName." fi
————————————————————
测试练习6时,都基于变量存在的情况下,若变量不存在时,会有如下提示:
#此处为逻辑错误,并非脚本语法错误,避免这种情况需要完善脚本,加入判断变量是否存在
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 UserName=$1 if id $1 &> /dev/null; then Uid=`grep "^$UserName:" /etc/passwd | cut -d: -f3` if [ $Uid -gt 499 ]; then echo "$1 is a common user." else echo "$1 is a administrator or system user." fi else echo "$1 is not exists." fi
#再次运行脚本,当输入并不存在的用户名时,就会提示用户不存在,修改后的语法结构叫做嵌套。
————————————————————
练习7:求200以内所有为3的整数倍的整数之和
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Sum=0 for I in `seq 1 200`; do if [ $[$I%3] -eq 0 ]; then Sum=$[$Sum+$I] fi done echo "Sum:$Sum" #该结构也是嵌套
练习8:给定一个用户,如果其UID等于GID,就说明这是个“good guy”,否则,“Bad guy.”
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if id $1 &> /dev/null;then if [ `id -u $1` -eq `id -G $1` ];then echo "This is a good guy." else echo "This is a bad guy." fi else echo "$1 is not exists." fi
练习9:计算100以内所有奇数的和以及所有偶数的和并分别显示之
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 EvenSum=0 OddSum=0 for I in `seq 1 100`; do if [ $[$I%2] -eq 0 ]; then EvenSum=$[$EvenSum+$I] else OddSum=$[$OddSum+$I] fi done echo "EvenSum:$EvenSum.OddSum:$OddSum." #或者 #!/bin/bash # Date: 2015-03-30 # Author: ArvinLau # Description: # Version: 1.0 EvenSum=0 OddSum=0 for I in `seq 1 2 100`;do OddSum=$[$OddSum+$I] done for I in `seq 2 2 100`;do EvenSum=$[$EvenSum+$I] done echo "EvenSum is $EvenSum,OddSum is $OddSum."
练习10:计算N以内所有奇数的和以及所有偶数的和;分别显示之;N是通过参数传递过来的正整数
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 EvenSum=0 OddSum=0 for I in `seq 1 $1`; do if [ $[$I%2] -eq 0 ]; then EvenSum=$[$EvenSum+$I] else OddSum=$[$OddSum+$I] fi done echo "EvenSum:$EvenSum.OddSum:$OddSum." #与练习9一样,只是这里引入一个变量$1传递参数,此时我们随便键入正整数即可得到想要的结果,例如键入999
————————————————————
补充1:通过参数传递n个正整数给脚本,求其和
#!/bin/bash # Sum=0 for I in `seq 1 $#`; do Sum=$[$Sum+$1] done echo $Sum #此处的`seq 1 $#`可以用$@替换,以达到生成一个遍历列表 #!/bin/bash # Sum=0 for I in $@; do Sum=$[$Sum+$1] done echo $Sum
补充2:通过参数传递n个正整数给脚本,求其和
#!/bin/bash # Sum=0 for I in `seq 1 $#`; do Sum=$[$Sum+$1] shift done echo $Sum #此处的shift实现位置参数轮替,当引用完变量后踢出,取列表中的下一个参数
————————————————————
练习11:写一个脚本,完成以下要求:
1、添加10个用户user1, user2, ..., user10;但要先判断用户是否存在,不存在而后再添加;
2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;
3、最后显示当前系统上共有多少个用户;
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Count=0 for I in `seq 1 10`; do if id User$I &> /dev/null; then echo "User$I is exists." else useradd User$I echo "Add User$I successfully." Count=$[$Count+1] #每加一个用户加1,不要写成$I fi done echo "Add $Count new user(s). " echo "Total users:`wc -l /etc/passwd | cut -d' ' -f1`"
练习12:写一个脚本,完成以下要求:
1、通过参数传递一系列用户名给脚本,让脚本添加这些用户;但要先判断用户是否存在,不存在而后再添加;
2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Count=0 for UserName in $@; do if id $UserName &> /dev/null; then echo "$UserName is exists." else useradd $UserName echo "Add $UserName successfully." Count=$[$Count+1] fi done echo "Add $Count new user(s)." echo "There is `wc -l /etc/passwd | cut -d' ' -f1` user(s)."
练习12:写一个脚本,判定用户的shell是否为bash
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 for UserName in $1; do if id $UserName &> /dev/null; then Shell=`grep "^$1:" /etc/passwd | cut -d: -f7` if [ $Shell == /bin/bash ]; then #如有需要此处的字符或变量用双引号,如字符间有空格时 echo "$1's shell is bash." Ret=5 else echo "$1's shell is not bash." Ret=7 fi else echo "$1 is not exists." Ret=9 fi done exit $Ret #echo $? 状态返回值即可判断执行的是脚本中哪一段命令
或
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Shell=`grep "^$1:" /etc/passwd | cut -d: -f7` if [ -z $Shell ]; then #值为空则为真,执行该语句 echo "No such user." exit 5 fi if [ $Shell == /bin/bash ]; then echo "Bash user." Ret=7 else echo "Not a bash user." Ret=9 fi exit $Ret
练习13:根据用户shell的结束符是否为sh来判定其是否为登录用户
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Shell=`grep "^$1:" /etc/passwd | cut -d: -f7` if [[ -z $Shell ]]; then echo "No such user." exit 5 fi if [ $Shell =~ sh$ ]; then echo "Login user." Ret=7 else echo "Not a login user." Ret=9 fi exit $Ret
练习14:写一脚本,给定用户,如果其不存在,就退出脚本
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if ! id $1 &> /dev/null; then echo "No such user." exit 5 fi
练习15:通过参数传递一个字符串给脚本,如果传递的字符串为“memory”或“Memory”,就以MB为单位显示当前主机的内存信息;否则,就显示/proc/uptime文件的内容
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if [ $1 == memory -o $1 == Memory ]; then free -m else cat /proc/uptime fi 或 #!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if [[ $1 =~ [Mm]emory$ ]]; then free -m else cat /proc/uptime fi
练习16:判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id一行中。如果其生产商为GenuineIntel,就显示其为Intel公司;如果其生产商为AuthenticAMD,就显示其为AMD公司;否则,就显示无法识别
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 Vendor=`grep vendor_id /proc/cpuinfo | uniq | cut -d: -f2` if [[ $Vendor =~ GenuineIntel$ ]]; then #因为cut时GenuineIntel前有空白字符,为了更准确取得信息可以写为 [[:space:]]*GenuineIntel$ echo "Intel." elif [[ $Vendor =~ AuthenticAMD$ ]]; then echo "AMD." else echo "Unknown." fi
练习17:通过参数传递给脚本一个字符串,如Fedora, Gentoo, Redhat,判断Linux发行版所处理主流发行系列:如果为fedora, centos, redhat,就显示RedHat;
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if [ $1 == Fedora -o $1 == Gentoo -o $1 == Redhat ]; then echo "The $1 is Redhat Series." elif [ $1 == Suse -o $1 == Opensuse ]; then echo "The $1 is Suse Series." elif [ $1 == Ubuntu -o $1 == Mint -o $1 == Debian ]; then echo "The $1 is Debian Series." else echo "The $1 is Unknown Series." fi
练习18:给定一个路径,判断如果为普通文件,显示之;如果为目录,显示之;否则,说无法识别;
#!/bin/bash # Date: 2015-04-02 # Author: ArvinLau # Description: # Version: 1.0 if [ ! -e $1 ]; then echo "No such file." exit 5 #不符合测试条件时,直接退出 fi if [ -f $1 ]; then echo "Common file." if [ -d $1 ]: then echo "Directory." else echo "Unknown file." fi