六、使用结构化命令

使用if-then语句

语法格式

if command
then
    commands
fi

注意:if是根据命令退出码来判断(echo $?=0),如果是0,则表示为真,执行后面的命令

举例

[root@tzPC ~]# cat if-1.sh
#!/bin/bash
if ls /mnt
then
        echo "It worked"
fi

 if-then-else语句

语法格式

if command ; then
    commands
else
    commands
fi

 举例

[root@tzPC if]# cat if_2.sh 
#!/bin/bash
testuser=tz
if grep $testuser /etc/passwd >/dev/null
then
        echo "The bash files for user $testuser are:"
        ls -a /home/$testuser/.b*
        echo
else
        echo "The user $testuser does not exist on this system."
        echo
fi

嵌套if

语法结构

if command1;then
    commands
elif command2;then
    commands
elif command3;then
    commands
...
else 
    more commands
fi

举例

查看tz用户是否存在

[root@tzPC ~]# ls -d /home/tz
/home/tz
[root@tzPC ~]# echo $?
0

 脚本

[root@tzPC ~]# cat if-3.sh
#!/bin/bash
read -p "input a username:" name
if grep $name /etc/passwd ;then
        echo "the user $name exists on this system!"
elif ls -d /home/$name;then
        echo "the user $name not exists on this system!"
        echo "$name has a home directory"
else
        echo "the user $name not exists on this system"
        echo "$name not has a direcotry"
fi

test命令

test命令用于检查某个条件是否成立,如果成立就会退出并返回状态码0。不成立就会返回非0退出状态码。

test命令可以判断三类条件

  • 数值比较
  • 字符串比较
  • 文件比较

语法格式

if test condition
then 
    commands
fi

语法格式2

注意方括号之间的空格

if [ condition ]
then
    commands
fi

如果不写condition会以非0的退出状态码退出

[root@tzPC test]# bash test6.sh 
No expression returns a False

#脚本如下 [root@tzPC test]#
cat test6.sh #!/bin/bash if test then echo "No expression returns a True" else echo "No expression returns a False" fi

 如果condition有内容,返回的退出码就为0,如果没有则不为0

[root@tzPC test]# bash test6.sh 
No expression returns a True

#脚本如下
[root@tzPC test]#
cat test6.sh #!/bin/bash my_variable="Full"
#my_variable="" 则会返回非0
if test $my_variable then echo "No expression returns a True" else echo "No expression returns a False" fi

数值比较

参数

说明

示例

-eq

等于则为真

n1 -eq n2

-ne

不等于则为真

n1 -ne n2

-gt

大于则为真

n1 -gt n2

-ge

大于等于则为真

n1 -ge n2

-lt

小于则为真

n1 -lt n2

-le

小于等于则为真

n1 -le n2

举例

[root@tzPC ~]# cat test-1.sh
#!/bin/bash
if test 2 -eq 1 ; then
        echo ok
else
        echo err
fi

 或者

[root@tzPC ~]# cat test-2.sh
#!/bin/bash
if [ 2 -eq 2 ] ;then
        echo ok
else
        echo err
fi

 举例

[root@tzPC test]# bash numeric_test.sh 
The test value 10 is greater than 5
The values are different
#脚本如下
[root@tzPC test]# cat numeric_test.sh 
#!/bin/bash
value1=10
value2=11
if [ $value1 -gt 5  ]
then 
        echo "The test value $value1 is greater than 5"
fi
#
if [ $value1 -eq $value2 ]
then 
        echo "The values are equal"
else 
        echo "The values are different"
fi

数值比大小

[root@tzPC ~]# cat test2.sh
#!/bin/bash
read -p "input var1 var2:" var1 var2
if [ $var1 -gt $var2 ] ;then
        echo "$var1 > $var2"
elif [ $var1 -lt $var2 ] ;then
        echo "$var1 < $var2"
else
        echo "$var1=$var2"
fi

 注意,bash shell只能处理整数,在condition 中写浮点数比较会报错。

字符串比较

参数.

说明

str1 == str2 或者

str1 = str2

检查str1 是否跟 str2相同

str1 != str2

检查str1 是否跟 str2不同

-z str1

检查str1 长度是否为0

-n str1

检查str1长度是否非0

str1 > str2

检查str1是否比str2大

str1 < str2

检查str1是否比str2小

举例

[root@tzPC ~]# cat test3.sh
#!/bin/bash
read -p "input your name :" name
if [ $name == "root" ] ;then
        echo "you are super administrator"
else
        echo "you are a general user"
fi

 

字符串比较需要注意

  • 大于号和小于号必须转义,要不然SHELL会把它当成重定向符号
  • 大于和小于它们的顺序和sort排序是不一样的
  • 在test比较测试中,它使用的是ASCII顺序,大写字母是小于小写字母的;sort命令使用的是系统的本地化语言设置中定义的排序顺序,对于英语,本地化设置制定了在排序中小写字母会出现在大写字母前。

举例

[root@tzPC test]# bash test4.sh
test > Test
#在比较测试中大写字母是小于小写字母的
[root@tzPC test]# sort testfile 
test
Test
#在sort中大写字母是大于小写字母的,sort默认从小到大排序

#脚本如下 [root@tzPC test]#
cat test4.sh #!/bin/bash var1=test var2=Test if [ $var1 \> $var2 ] ;then echo "$var1 > $var2" else echo "$var1 < $var2" fi

 -z跟-n判断未被定义的变量长度会被判为0

文件比较

参数

.说明

 -e file

检查文件或目录是否存在

-r file

检查文件存在且可读

-w file

检查文件存在且可写

-x file

检查文件存在且可执行

-s file

检查文件存在且至少有一个字符

-d file

检查文件存在且为目录

-f file

检查文件存在且为普通文件

-c file

检查文件存在且为字符型文件

-b file

检查文件存在且为块特殊文件

file1 -nt fle2

检查file1是否比file2新

file1 -ot file2

检查file1是否比file2旧

检查目录是否存在

-d会检查指定的目录是否存在于系统中

[root@tzPC script]# bash test11.sh 
The /home/tz directory exists
/home/tz
[root@tzPC script]#
cat test11.sh #!/bin/bash jump_directory=/home/tz if [ -d $jump_directory ];then echo "The $jump_directory directory exists" cd $jump_directory pwd else echo "The $jump_directory direcotry does not exist" fi

 检查文件或目录是否存在

#!/bin/bash
if [ -e /etc/passwd ] ; then
        echo ok
else
        echo err
fi 

 举例

[root@tzPC ~]# test -e /etc/aaa.txt && echo ok || echo err

 检查文件是否存在

[root@tzPC script]# bash test13.sh 

The item being checked: /root

The item,/root,does exits.
But is it a file?

No,/root is not a file.
#脚本如下
[root@tzPC script]# cat test13.sh
#!/bin/bash
item_name=$HOME
echo
echo "The item being checked: $item_name"
echo
if [ -e $item_name ]; then
        echo "The item,$item_name,does exits."
        echo "But is it a file?"
        echo
        if [ -f $item_name ];then
                ehco "Yes,$item_name is a file."
        else
                echo "No,$item_name is not a file."
        fi
else 
        echo "The item,$item_name,does not exist."
        echo "Nothing to update"
fi

 

检查所属关系

-O可以测试你是否是文件的属主

root@tzPC script]# bash test18.sh 
You are the owner of the /etc/passwd file
[root@tzPC script]# cat test18.sh
#!/bin/bash
if [ -O /etc/passwd ];then
        echo "You are the owner of the /etc/passwd file"
else 
        echo "Sorry,you are not the owner of the /etc/passwd file"
fi

检查默认属主关系

-G只会检查文件的默认组,是否为用户的默认组,并不会检查用户所属的所有组。

检查文件日期

对两个文件的创建日期进行比较

-nt比较一个文件是否比另一个文件新

-ot比较一个文件是否比另一个文件旧

注意:使用前须先确认文件是否存在

[root@tzPC script]# bash test20.sh
The test18.sh file is newer than test11.sh
the test11.sh file is older than the test18.sh
[root@tzPC script]# ll
总用量 16
-rw-r--r--. 1 root root 199 8月  16 22:31 test11.sh
-rw-r--r--. 1 root root 158 8月  16 23:13 test18.sh

#脚本如下
[root@tzPC script]# cat test20.sh #!/bin/bash if [ test11.sh -nt test18.sh ];then echo "The test11.sh file is newer than test18.sh" else echo "The test18.sh file is newer than test11.sh" fi if [ test11.sh -ot test18.sh ];then echo "the test11.sh file is older than the test18.sh" fi

清空日志目录

#!/bin/bash
# clear /var/log/messages

#确定当前是root用户
if [ $USER != "root" ];then
    echo "你必须使用root用户才能执行脚本"
    exit 10    #直接退出,并返回10
fi

#判断文件是否存在
if [ ! -f /var/log/messages ];then
    echo "文件不存在"
    exit 12
fi

#保留最近100行的日志内容
tail -100 /var/log/messages > /var/log/mesg.tmp

#日志清理
>/var/log/messages
#cat /dev/null > /var/log/messages

mv /var/log/mesg.tmp /var/log/messages
echo "Logs clean up"
注:退出码 exit ,取值范围是0-255

 退出码可以使用$?得到

复合条件测试

判断第一种:两个条件都为真或有一个为真就执行

注意&&在[]外

if [ command1 ] && (||) [ command2 ]; then    
   commands
elif [ command3 ] && (||) [ command4 ]; then
    commands
else
    commands
fi

 判断第二种

注意-a在[]内

if [ command1 -a (-o) command2 -a (-o) command3 ]; then
elif [command3  -a (-o) command4 ]; then
else
   commands
fi

 判断第三种

[[...]]支持*,<,>等符号且不需要转义

if [[ command1 && (||) command2 ]]; then
  commands elif [[ command3 && (||) command4 ]]; then else commands fi

 使用双括号(())

  • 双括号可以在比较过程中使用高级数学表达式。
  • 双括号中可以赋值,且不用转义。
符号 描述
val++ 后增
val-- 后减
++val 先增
--val 先减
! 求反
- 位求反
** 幂运算
<< 左位移
>> 右位移
& 位布尔和
| 位布尔或
&& 逻辑和
|| 逻辑或

注意括号左右要有空格。

[root@tzPC script]# bash test23.sh 
The square of 10 is 100
[root@tzPC script]# cat test23.sh 
#!/bin/bash
val1=10
if (( $val1 ** 2 > 90 ));then
        ((val2 =$val1 ** 2 ))
        echo "The square of $val1 is $val2"
fi

 使用双方括号

  • 双方括号支持模式匹配
  • [[...]]支持*,<,>等符号且不需要转义

举例

[root@tzPC ~]# if [[ $USER == ro*  ]] ;then echo "hello,$USER" ;else echo "$USER is not root";  fi
hello,root

 当只有一个[],r*表示字符串r*,而不是r通配符*

[root@tzPC ~]# if [ $USER == ro*  ] ;then echo "hello,$USER" ;else echo "$USER is not root";  fi
root is not root

这时候需要这样写

[root@tzPC ~]#  if [[ $USER == [a-z]oot ]] ; then echo "hello,$USER" ; else echo $USER not ; fi
hello,root

 

[[ 。。。 ]]和[ 。。。]的区别汇总:

1、所有的字符与逻辑运算符直接用“空格”分开,不能连到一起。

2、在[… ]表达式中,常见的<需要加转义符\,大小比较

3、进行逻辑运算符&& 、||比较时;如果用的[ ]符号,则用在外面,如[… ] && [… ] || [ …]如果在[…]里面进行逻辑与或的比较,则用-a、-o进行表示,如[ x = y –a x < z –o x > m ]

4、[[… ]] 运算符只是[… ]运算符的扩充;能够支持>符号运算不需要转义符;它还是以字符串比较大小。里面支持逻辑运算符 ||  && , 不再使用-a 、-o

5、[[…]] && 而不是 -a 表示逻辑“与”;用 || 而不是 -o表示逻辑“或”

6、[[… ]]可以进行算术扩展,而[ ... ]不可以

7、[[...]]能用正则,而[...]不行

8、双括号((  ))用于数学表达式

9、双方括号号[[  ]]用于高级字符串处理,比如“模糊匹配”

shell常见通配符:

字符

含义

实例

*

匹配 0 或多个字符

a*b  a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。

?

匹配任意一个字符

a?b  a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。

[list] 

匹配 list 中的任意单一字符

a[xyz]b   a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。

[!list] 

匹配 除list 中的任意单一字符

a[!0-9]b  a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。

[c1-c2]

匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z]

a[0-9]b  0与9之间必须也只能有一个字符 如a0b, a1b... a9b。

{string1,string2,...}

匹配 sring1 或 string2 (或更多)其一字符串

a{abc,xyz,123}b    a与b之间只能是abc或xyz或123这三个字符串之一。

举例

[root@tzPC ~]# ls /etc/*.conf
/etc/asound.conf  /etc/host.conf   /etc/libaudit.conf   /etc/man_db.conf    /etc/rsyslog.conf   /etc/sudo-ldap.conf
/etc/dracut.conf  /etc/kdump.conf  /etc/libuser.conf    /etc/mke2fs.conf    /etc/sestatus.conf  /etc/sysctl.conf
/etc/e2fsck.conf  /etc/krb5.conf   /etc/locale.conf     /etc/nsswitch.conf  /etc/sos.conf       /etc/vconsole.conf
/etc/fuse.conf    /etc/ld.so.conf  /etc/logrotate.conf  /etc/resolv.conf    /etc/sudo.conf      /etc/yum.conf
[root@tzPC ~]# ls /etc/???.conf
/etc/sos.conf  /etc/yum.conf
[root@tzPC ~]# touch /home/tz/a{1,2,3}.txt
[root@tzPC ~]# ls /home/tz/
a1.txt  a2.txt  a3.txt  root
[root@tzPC ~]# ls /home/tz/a[123].txt
/home/tz/a1.txt  /home/tz/a2.txt  /home/tz/a3.txt
[root@tzPC ~]# ls /home/tz/a[1,2,3].txt
/home/tz/a1.txt  /home/tz/a2.txt  /home/tz/a3.txt

case命令

case命令会将指定的变量与不同模式进行比较。

根据变量的不同取值进行比较从而分别执行不同命令操作

适用于多分支,是一个多选择语句

case     变量或表达式     in
              变量或表达式1)
                     命令序列1
                     ;;
            变量或表达式2)
                     命令序列2
                     ;;
                     ……
                     *)  
                     默认命令序列
 esac

举例

[root@tzPC script]# cat test26.sh
#!/bin/bash
case $USER in
tz | root)
        echo "Welcome,$USER"
        echo "Please enjoy your visit"
        ;;
testing)
        echo "Special testing account"
        ;;
rich)
        echo "Do not forget to log off when you're done"
        ;;
*)
        echo "Sorry,you are not allowed here"
        ;;
esac

 举例2

[root@tzPC ~]# cat case1.sh
#!/bin/bash
cat <<eof
***************
*  1. backup  *
*  2. copy    *
*  3. quit    *
***************
eof
read -p "Input a choose:" OP
case $OP in
        1|backup)
                echo "BACKUP..."
        ;;
        2|copy)
                echo "COPY..."
        ;;
        3|quit)
                exit
        ;;
        *)
                echo "error"
esac

 exit 后边写返回值,默认是0,可以通过$?取得。

例2:编写一个启动apache服务脚本

安装httpd服务

yum -y install httpd

 脚本

[root@tzPC ~]# cat case2.sh
#!/bin/bash
case $1 in
        start)
                systemctl $1 httpd
                ps aux|grep httpd
        ;;
        stop)
                systemctl $1 httpd
                ps aux|grep httpd
        ;;
        status)
                systemctl $1 httpd
                ps aux|grep httpd
        ;;
        restart)
                systemctl $1 httpd
                ps aux|grep httpd
        ;;
        *)
                echo "USAGE: $0 start|stop|restart"
esac

 学习来自:《Linux命令行与Shell脚本大全 第3版》第12章

 

posted @ 2020-07-16 14:06  努力吧阿团  阅读(192)  评论(0编辑  收藏  举报