Shell编程之条件判断与流程控制

时间:2022-08-27 05:37:29

一、条件判断式语句

1-1.概述

用来判断是与否,客观的而非主观判断,用于进行基本的管理

1-2.按文件类型判断

补充:

&& 命令1&&命令2 逻辑与(没有数据传递)
当命令1正确执行,则命令2才会执行
当命令1执行不正确,则命令2不会执行

|| 命令1||命令2 逻辑或(没有数据传递)
当命令1执行不正确时,命令2才会执行
当命令1正确执行时,命令2不会执行

按文件类型判断

记住蓝色部分

两种判断格式:

test –e /root/install.log
[-e /root/install.log]; e:exist
[-d /root] && echo “yes” || echo “no”

第一个判断命令如果正确执行,则打印“yes”,否则打印“no”

注意Linux中0表示命令成功;1,表示命令失败,区别于Python中对象为空数字为0代表假,非0非空代表真。

例子:

[root@localhost ~]# ls

anaconda-ks.cfg install.log …

[root@localhost ~]# [-e /root/install.log]

[root@localhost ~]# echo $?

0

[root@localhost ~]# [-e /root/install,login] | echo $?

[root@localhost ~]# 1

[root@localhost ~]# [-e /root/install.log] && echo yes || echo no

yes

[root@localhost ~]# [-e /root/install.log] && echo yes || echo no

no

其实上面是if的单分支语句,注意顺序不可以变化,如果no执行了那么yes也会出现,毕竟正确执行了

1-3.按文件权限判断

按文件权限进行判断

例子:[-w student.txt] && echo “yse” || echo “no”

判断文件是否拥有写权限

[root@localhost ~]# ll

总用量 52

-rw-r—r—.1 root root 7690 8月 14 16:34 install.log

[root@localhost ~]# [-w install.log] && echo yes || echo no

yes

不会判断是所有者有写权限还是所属者有写权限还是其他人有写权限,当然,我们可以用字符截取三个位置的权限分布情况进行分析

1-4.两个文件之间的比较

测试选项
作用

文件1 –nt 文件2
判断文件1的修改时间是否比文件2的新(如果新则返回真)n,new;t,time
文件1 –ot 文件2
判断文件1的修改时间是否比文件2的旧(如果旧则返回真)o,old;t,time
文件1 –ef 文件2
判断文件1是否和文件2的inode号一直,可以理解为两个文件判断是否属于同一个文件,用于判断硬链接的很好的方法,s

因为硬链接的inode号一致,软链接不一样

[root@localhost ~]# ln /root/student.txt /tmp/stu

[root@localhost ~]# [/root/student.txt –ef /tmp/stu] && echo yes || echo no

yes

[root@localhost ~]# ll –i

262154 -rw-r—r—.2 root root 60 8月 14 16:50 student.txt

[root@localhost ~]# ll –i /tmp/stu

262154 –rw-r—r—.2 root root 60 8月 14 16:50 /tmp/stu

源文件和链接文件的inode是一样的

.硬链接特征:
1、拥有相同的i节点和存储block块(一般4KB一个block),可以看做是同一个文件
相当于一个存储文件的不同的获取入口,镜像一样存储double份
2、只能对已经存在的文件进行创建
3、不能跨分区 ,不能交叉文件系统进行硬链接的创建
4、不能针对目录使用,只能针对文件创建

5、删除一个硬链接文件不影响其它有相同inode号的文件

.软链接特征:
1、类似windows快捷方式,方便打开
2、软链接拥有自己的i节点和block块,但是数据块中保存原文件的文件名和i节点号,并没有实际的文件数据,而是原文件的i节点和block块
3、lrwxrwxrwx |软链接
软链接文件权限都为rwxrwxrwx,查看软链接文件的权限,区别于原文件
4、修改任意文件,另一个都改变
5、删除原文件,软链接不能使用
限制少,而且灵活

1-5.两个整数之间比较

测试选项
作用

整数1 –eq 整数2
判断整数1是否和整数2相等(相等为真)
整数1 –ne 整数2
判断整数1是否和整数2不相等(不相等为真)
整数1–gt 整数2
判断整数1是否大于整数2(大于为真)
整数1 –lt 整数2
判断整数1是否小于整数2(小于为真)
整数1 –ge 整数2
判断整数1是否大于等于整数2(大于等于为真)
整数1 –le 整数2
判断整数1是否小于等于整数2(小于等于为真)

例子:

[root@localhost ~]# [23 –ge 22] && echo yes || echo no

yes

判断23是否大于等于22

[root@localhost ~]# [23 –le 22] && echo yes || echo no

no

判断23是否小于等于22,no

1-6.字符串的判断

测试选项
作用

-z 字符串
判断字符串是否为空(为空返回真)
-n 字符串
判断字符串是否为空(非空返回真)Null
字符串1 == 字符串2
判断字符串1是否和字符串2相等(相等返回真)
字符串1 != 字符串2
判断字符串1是否和字符串2不想等(不想等返回真)

例子:

1).判断字符串是否为空

[root@localhost ~]# name=fengj

[root@localhost ~]# [-z $name] && echo yes || echo no

no

不为空

[root@localhost ~]# name=””

[root@localhost ~]# [-z $name] && echo yes || echo no

yes

为空

2).判断字符串是否相等

[root@localhost ~]# aa=11

[root@localhost ~]# bb=22

[root@localhost ~]# [“ aa== bb”] && echo yes || echo no

no

[root@localhost ~]# [“ aaeq bb”] && echo yes || echo no

no

[root@localhost ~]# aa=22

[root@localhost ~]# [“ aa== bb”] && echo yes || echo no

yes

[root@localhost ~]# [“ aaeq bb”] && echo yes || echo no

yes

判断两个变量的值是否相等,不想等返回假,记得字符串加上双引号“$aa”,没加可能出现错误

1-7.多重条件的判断

测试选项
作用

判断1 –a 判断2
逻辑与,判断1和判断2都成立,最终结果才为真;and
判断1 –o 判断2
逻辑或,判断1和判断2只要有一个为真,最终结果就为真;or
!判断
逻辑非,是原始的判断式取反

例子1:

[root@localhost ~]# aa=11

[root@localhost ~]# [-n “ aaa aa”-gt 23] && echo yes || echo no

no

-n “$aa”:判断aa是否为空

-gt “$ss”:判断aa的值是否大于23

-a:逻辑与,因为aa<23,为假,所以结果也为假

[root@localhost ~]# [-n “ aaa aa”-gt 2] && echo yes || echo no

yes

二、单分支if语句

2-1.概述

Shell的语法结构不同于一些常见的语言

1).目的:

掌握语法结构

了解Shell的作用

分析编程思想

2).建立编程思想的方法:

熟悉Linux基本命令、规范、语法及Shell语法

实际与所学相互结合,了解每个程序的思路,也就是编程思想

具体方式:

抄写程序并正确运行

为程序打上注释

删除注释,为代码重新加注释

看注释写代码

删除代码程序,从头开始写

2-2.单分支if语句

格式:
if [条件判断式];then

  程序

fi

  或者

if [条件判断式]

 then

程序

fi

fi来标识结束,finish

解释:

if语句使用fi结尾,和一般的语言使用大括号结尾不同

[条件判断式]就是使用test命令判断,所以中括号和条件判断式之间必须有空格

then后面跟符合条件之后执行的程序,可以放在中括号[]之后,用分号”;”分割,也可以换行写入,就不需要分号“;”了

1).例子1:判断登录用户是否是root

!/bin/bash

test=$(env | grep “USER”| cut –d “=”-f2)

if [ “$test” == root ]

      then

echo “Current user is root.”

fi

[root@localhost ~]# ls

anaconda-ks.cfg sh ….

[root@localhost ~]# cd sh/

[root@localhost sh]# ls

b1.sh hello.sh read.sh

[root@localhost sh]# whoami

root

[root@localhost sh]# vi if_1.sh

!/bin/bash

test=$(env | grep “USER”| cut –d “=”-f2) #提取env环境变量中USER的值

注意,在shell编程中可以先输出结果测试后在接下来完成剩下的代码,如这里可以先

echo $test

if [ “$test” == root ] #如果所提取的test值==root

      then

echo “Current user is root.”#返回用户比较结果

fi

~

wq

[root@localhost sh]# chmod 755 if_1.sh

[root@localhost sh]# ./if_1.sh

Current user is root

查看环境变量,截取到USER,然后进行行提取,接下来根据=号进行列提取

补充:|,管道符,命令1 | 命令2,命令1的结果作为命令2的输入项

2).例子2:判断分区使用率

!/bin/bash

统计分区使用率

rate=(df –h | grep “/dev/sda3”| awk ‘{print5}’| cut –d “%”-f1)

把根分区使用率作为变量值赋予rate

df -h:显示分区情况

grep “/dev/sda3”提取行/dev/sda3

awk ‘{print 5}’:把行/dev/sda3第五列5数据提取出来

cut –d “%”-f1:使用cut 提取“%”前第一列的数字

以上提取出来的就是分区使用率,赋值给rate

if [ “$rate” –ge 80 ]

    then

echo “Warning! /dev/sda3 will full soon”

fi

~

wq

[root@localhost sh]# df –h

文件系统 容量 已用 可用 已用% 挂载点

/dev/sda5 18G 1.8G 15G 11% /

tmpfs 504M 0 504M 0% /dev/shm

/dev/sda1 194M 26M 158M 15% /boot

/dev/sda2 2.0G 35M 1.8G 2% /home

h:human,人性化显示

[root@localhost sh]# df –h | grep /

/dev/sda5 18G 1.8G 15G 11% /

tmpfs 504M 0 504M 0% /dev/shm

/dev/sda1 194M 26M 158M 15% /boot

/dev/sda2 2.0G 35M 1.8G 2% /home

[root@localhost sh]# df –h | grep /dev/sda5

/dev/sda5 18G 1.8G 15G 11% /

[root@localhost sh]# df –h | grep /dev/sda5 | awk ‘{print $5}’

11%

[root@localhost sh]# df –h | grep /dev/sda5 | awk ‘{print $5}’| cut –d “%” –f 1

11

[root@localhost sh]# vi if_2.sh

!/bin/bash

统计分区使用率

rate=(df –h | grep “/dev/sda5”| awk ‘{print5}’| cut –d “%”-f1)

if [ “$rate” –ge 10 ]

    then

echo “Warning! /dev/sda5 will full soon”

fi

~

[root@localhost sh]# chmod 755 if_2.sh

[root@localhost sh]# ./if_2.sh

Warning! /dev/sda5 will full soon

三、双分支if语句

格式:
if [ 条件判断式 ]

   then

条件成立时,执行的程序

else

条件不成立时,执行的程序

fi

补充:
接收键盘输入

read [选项] [变量名]

选项:

  -p ”提示信息“:在等待read输入的时候,输出提示信息

-t 秒数 :read命令会一直等待用户输入,使用此选项可以指定等待时间

-n 字符数:read 命令只接收指定的字符数,就会执行

-s :隐藏输入的数据,适用于机密信息的输入

1.判断输入的是否是同一个目录

!/bin/bash

判断输入的文件是否是一个目录

read –t 30 –p “Please input a directory:” dir

read:读取

-t 30 :等待20秒

-p :输出一个提示信息“Please input a directory”

dir:赋给变量dir

if [ –d “$dir”] #-d:判断文件是否存在,并且是否为目录文件(是目录则为真)

     then 

echo “yes” #是目录

else

echo “no” #不是目录

fi

[root@localhost sh]# vi if_3.sh

!/bin/bash

read –t 30 –p “Please input a directory:” dir

if [ –d “$dir”]

     then 

echo “yes”

else

echo “no”

fi

~

wq

[root@localhost sh]# chmod 755 if_3.sh

[root@localhost sh]# ./if_3.sh

Please input a directory: /root

yes

[root@localhost sh]# ./if_3.sh

Please input a directory: sda110

no

2.判断Apache服务是否启动

apache,web服务

运维平台:美工+程序+数据库+web服务+系统环境Linux+服务器+域名+IP+网络+…

Netcraft:网站信息统计

[root@localhost ~]# ps aux

查看系统所有正在运行的应用和服务

[root@localhost ~]# ps aux | grep httpd

root 6369 0.0 0.3 11188 3316 ? Ss 17:52 0:00 /usr/sbin/httpd

apache 6372 0.0 0.2 11188 2080 ? S 17:52 0:00 /usr/sbin/httpd

root 6564 0.0 0.0 5960 740 pts/0 s+ 17:52 0:00 grep –color=auto httpd

[root@localhost ~]# service httpd stop

停止 httpd: [确定]

[root@localhost ~]# ps aux | grep httpd

root 6564 0.0 0.0 5960 740 pts/0 s+ 17:52 0:00 grep –color=auto httpd

[root@localhost ~]#

依旧包含了httpd相关的grep命令,我们可以取反

[root@localhost ~]# service httpd start

正在启动httpd: httpd: Could not reliably datermine the server’s fully qualified domain name, using ::1 for ServerName [确定]

[root@localhost ~]# ps aux | grep httpd | grep –v grep

root 6369 0.0 0.3 11188 3316 ? Ss 17:52 0:00 /usr/sbin/httpd

apache 6372 0.0 0.2 11188 2080 ? S 17:52 0:00 /usr/sbin/httpd

没有了grep相关的httpd服务了

脚本代码:

!/bin/bash

tesh =$(ps aux | grep httpd | grep –v grep)

截取httpd进程,并把结果赋予变量test

if [ –n “$test” ]#如果test的值不为空,则执行then中命令

-n 字符串,判断字符串是否为空

        then

echo “$(date) httpd is ok!”>> /tmp/autostart-acc.log

else

/etc/rc.d/init.d/httpd start &>/dev/null

/etc/rc.d/init.d/httpd start :apache标准启动命令

&> :输出重定向,把输出结果不论正确错误输出到指定目录或者文件

              echo “$(date) restart httpd!!”>> /tmp/autostart-err.log

fi

补充:

输出重定向:
类型 符号 作用
标准输出重定向 命令>文件 以覆盖的方式,把命令的正确输出输出到的文件或设备当中
命令>>文件 以追加的方式,把命令的正确输出输出到指定的文件或设备当中
标准错误输出重定向 错误命令2>文件 以覆盖的方式,把命令的错误输出输出到指定的文件或设备当中
错误命令2>>文件 以追加的方式,把命令的错误输出输出到指定的文件或设备当中
正确输出和错误输出 命令>文件 2>&1 以覆盖的方式,把命令的正确和错误输出输出 同时保存到指定的文件当中
命令>>文件 2>&1 以追加的方式,把命令的正确和错误输出输出到指定的文件当中
命令&>文件 以覆盖的方式,把正确输出和错误输出都保存在同一个文件当中
命令&>>文件 以追加的方式,把命令的正确和错误输出输出到指定的文件当中
命令>>文件1 2>>文件2 以追加的方式,把命令的正确输出保存到文件1,把错误的输出保存到文件2

   通过输出重定向,把输出结果保存起来,可以实现无人值守

[root@localhost sh]# vi if_4.sh

!/bin/bash

tesh =$(ps aux | grep httpd | grep –v grep)

截取httpd进程,并把结果赋予变量test

if [ –n “$test” ]#如果test的值不为空,则执行then中命令

-n 字符串,判断字符串是否为空

        then

echo “$(date) httpd is ok!”>> /tmp/autostart-acc.log

else

/etc/rc.d/init.d/httpd start &>/dev/null

/etc/rc.d/init.d/httpd start :apache标准启动命令

&> :输出重定向,把输出结果不论正确错误输出到指定目录或者文件

              echo “$(date) restart httpd!!”>> /tmp/autostart-err.log

fi

~wq

[root@localhost sh]# chmod 755 if_4.sh

[root@localhost sh]# ./if_4.sh

18:53 httpd is ok!

[root@localhost sh]# service httpd stop

[root@localhost sh]# ./if_4.sh

18:54 restart httpd!!

正在启动httpd: httpd: Could not reliably datermine the server’s fully qualified domain name, using ::1 for ServerName [确定]

在apache2.4版本之后启动基本都会报错,只是不认识主机名,但其实仍然启动了

[root@localhost sh]# ./if_4.sh

18:54 httpd is ok!

我们可以把脚本加入到linux的用户计划,让ta自动运行

缺陷:
如果你把if_4.sh改成了httpd_if_4.sh之后会发现即使关闭了服务,仍然会提示:“httpd is ok!”

[root@localhost sh]# mv if_4.sh httpd_if_4.sh

[root@localhost sh]# ./httpd_if_4.sh

httpd is ok

[root@localhost sh]# service is stop

停止 httpd: [确定]

[root@localhost ~]# ps aux | grep httpd | grep –v grep

root 6369 0.0 0.3 11188 3316 ? Ss 17:52 0:00 /usr/sbin/httpd

apache 6372 0.0 0.2 11188 2080 ? S 17:52 0:00 /usr/sbin/httpd

[root@localhost sh]# ./httpd_if_4.sh

httpd is ok

关闭服务依旧显示ok,所以要避免命名时不要带有httpd

改进:根据端口来判断服务是否启动
四、多分支if语句

格式:
if [ 条件判断式1 ]

       then

当条件判断式1成立时,执行程序1

elif [ 条件判断式2 ]

        then

当条件判断式2成立时,执行程序2

…更多条件判断式与程序…

else

         所有条件都不成立是,执行这部分

fi

1.简介

单分支只有一个判断,然后就直接运行了;双分支有一个符合条件的分支和一个不满足的情况;多分支有多个条件以及对应的程序。

2.实例:计算器

进行数值运算:

1.有没有输入内容

2.是不是数值

3.什么运算,是什么运算符(加减乘除)

4.执行运算操作

代码:

!/bin/bash

字符界面加减乘除计算器

read – t 30 –p “Please input num1:”num1

read –t 30 –p “Please input num2:”num2

通过read命令接收要计算的数值,并赋予num1和num2

read –t 30 –p “Please input a operator:”ope

通过read命令接收要计算的符号,并赋予ope,进行接下来的运算准备

if [ –n “ num1an num2”-a –n “$ope” ]

-n:判断字符串是否为空,非空返回真

-a :逻辑与and,判断1和判断2都成立,最终结果才为真

第一次判断,判断num1和num2以及ope是否有值

           then

test1=$(echo $num1 | sed‘s/[0-9]//g’)

test2=$(echo $num2 | sed ‘s/[0-9]//g’)

定义变量test1和test2的值为$(命令)的结果

后续命令作用,把变来那个test1的值替换为空,吐过能够替换为空,证明num1的值为数字

如果不能替换为空,证明num1,num2的值非数字,我们使用这种方法判断变量num1,num2的值

            if  [ –z “$test1” –a –z “$test2”]

第二层判断,用来判断num1和num2是否为数值

如果变量test1和test2的值为空,则证明num1和num2是数字

            then

#如果test1和test2是数字,则执行以下命令

if [ “$ope” == ‘+‘ ]

#第三层判断用来确认运算符

then

sum = $(( $num1 + $num2))

#如果是加号则执行加法程序

elif [ “$ope” == ‘-’]

then

sum = $(( $num1 – $num2))

#如果是减号则执行减法程序

elif [ “$ope” == ‘*’]

then

sum = $(( $num1 * $num2))

#如果是减号则执行乘法程序

elif [ “$ope” == ‘/’]

then

sum = $(( $num1 / $num2))

#如果是减号则执行除法程序

else

echo “Please enter a valid symbol”

#如果运算符不匹配,提示输入有效的符号

exit 10

#并退出程序,返回错误代码10

fi

else

#如果test1和test2不是数值

echo “Please enter a valid value”

#则提示输入和法的值

exit 11

#退出并返回错误代码11

else

         echo “Please input num”

exit 12

fi

详细执行:
[root@localhost ~]# cd sh

[root@localhost sh]# vi if_5.sh

!/bin/bash

字符界面加减乘除计算器

read – t 30 –p “Please input num1:”num1

read –t 30 –p “Please input num2:”num2

通过read命令接收要计算的数值,并赋予num1和num2

read –t 30 –p “Please input a operator:”ope

通过read命令接收要计算的符号,并赋予ope,进行接下来的运算准备

if [ –n “ num1an num2”-a –n “$ope” ]

           then

test1=$(echo $num1 | sed‘s/[0-9]//g’)

test2=$(echo $num2 | sed ‘s/[0-9]//g’)

if [ –z “$test1” –a –z “$test2”]

then

#如果test1和test2是数字,则执行以下命令

if [ “$ope” == ‘+‘ ]

#第三层判断用来确认运算符

then

sum = $(( $num1 + $num2))

#如果是加号则执行加法程序

elif [ “$ope” == ‘-’]

then

sum = $(( $num1 – $num2))

#如果是减号则执行减法程序

elif [ “$ope” == ‘*’]

then

sum = $(( $num1 * $num2))

#如果是减号则执行乘法程序

elif [ “$ope” == ‘/’]

then

sum = $(( $num1 / $num2))

#如果是减号则执行除法程序

else

echo “Please enter a valid symbol”

#如果运算符不匹配,提示输入有效的符号

exit 10

#并退出程序,返回错误代码10

fi

else

#如果test1和test2不是数值

echo “Please enter a valid value”

#则提示输入和法的值

exit 11

#退出并返回错误代码11

else

         echo “Please input num”

exit 12

fi

~

wq

[root@localhost sh]# chmod 755 if_5.sh

[root@localhost sh]# ./if_5.sh

Please input num1:

Please input num2:

Please input a operator: *

Please input num

[root@localhost sh]# echo $?

12

[root@localhost sh]# ./if_5.sh

Please input num1: 7

Please input num2: 8

Please input a operator: *

7 * 8 = 56

3.实例:判断用户输入的是什么文件

代码:

!/bin/bash

判断用户输入的是什么文件

read –p “Please input a filename :”file

接收键盘的输入,并赋予变量file

if [ –z “$file” ]

判断file是否为空,-z:判断字符串是否为空

  then 

echo “Error,please input a filename”

exit 1

elif [ ! –e “$file” ]

判断file的值是否存在,-e:判断该文件是否存在

            then

echo “Your input is not a file!”

exit 2

elif [ –f “$file” ]

判断file的值是否为普通文件,-f:判断该文件是否存在,并且是否是普通文件

            then

echo “File is a regulare file!”

elif [ –d “$file” ]

判断file的值是否是目录文件,-d : 判断文件是否存在,并且是否是目录文件

             then

echo “File is a directory!”

else

echo ”File is an other file!”

fi

具体实现:
[root@localhost sh]# vi if_6.sh

!/bin/bash

判断用户输入的是什么文件

read –p “Please input a filename :”file

接收键盘的输入,并赋予变量file

if [ –z “$file” ]

判断file是否为空,-z:判断字符串是否为空

  then 

echo “Error,please input a filename”

exit 1

elif [ ! –e “$file” ]

判断file的值是否存在,-e:判断该文件是否存在

            then

echo “Your input is not a file!”

exit 2

elif [ –f “$file” ]

判断file的值是否为普通文件,-f:判断该文件是否存在,并且是否是普通文件

            then

echo “File is a regulare file!”

elif [ –d “$file” ]

判断file的值是否是目录文件,-d : 判断文件是否存在,并且是否是目录文件

             then

echo “File is a directory!”

else

echo ”File is an other file!”

fi

~

~

wq

[root@localhost sh]# chmod 755 if_6.sh

[root@localhost sh]# ./if_6.sh

Please input a filename :

Error,please input a filename

[root@localhost sh]# echo $?

1

[root@localhost sh]# ./if_6.sh

Please input a filename : sdaaaa

Your input is not a file!

[root@localhost sh]# ./if_6.sh

Please input a filename : /root

/root File is a directory!

[root@localhost sh]# ./if_6.sh

Please input a filename : /root/sh/if_6.sh

/root/sh/if_6.sh File is a regulare file!

[root@localhost sh]# ./if_6.sh

Please input a filename : /dev/sda1

/dev/sda1 File is an other file!

五、多分支case语句

case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if可以判断多种条件关系

格式:
case $变量名 in

      “值1”)

如果变量的值等于值1,则执行程序1

;;

“值2”)

如果变量的值等于值2,则执行程序2

;;

…省略其他分支…

         *)

如果变量的值都不是以上的值,则执行此程序

;;

esac

注意:分号不要忘了,还有结尾是easc,

具体事例:
[root@localhost ~]# cd sh

[root@localhost sh]# vi case.sh

!/bin/bash

read –t 30 –p “Please input your choose:Yes/No” cho

case “$cho” in

        “Yes”)

echo “Your choose is Yes”

;;

“yes”)

echo “Your choose is Yes”

;;

“no”)

echo “Your choose is No”

;;

“No”)

echo “Your choose is No”

;;

*)

echo “Error input”

;;

esac

~

~

wq

[root@localhost sh]# chmod 755 case.sh

[root@localhost sh]# ./case.sh

Please input your choose:Yes/No Yes

Your choose is Yes

[root@localhost sh]# ./case.sh

Please input your choose:Yes/No yes

Your choose is Yes

[root@localhost sh]# ./case.sh

Please input your choose:Yes/No No

Your choose is No

[root@localhost sh]# ./case.sh

Please input your choose:Yes/No no

Your choose is No

[root@localhost sh]# ./case.sh

Please input your choose:Yes/No 123

Error choose

运行速度快,主要用于一些直接的选择,类似于ABCD,1234,地名之类可以确定的值

六、for循环

重复型循环重要语句

格式:
for 变量 in 值1 值2 值3

     do

程序

done

例子1:

[root@localhost sh]# vi for_1.sh

!/bin/bash

for i in 1 2 3 4 5

    do

echo “$i”

done

~

例子2:批量解压缩脚本

补充:
压缩命令
常用压缩格式: .zip .gz .bz2 .tar.gz .tar.bz2
.rar压缩率高

(1).zip格式压缩
.zip压缩文件名 源文件
#压缩文件
.zip -r 压缩文件名 源目录
#压缩目录
[root@localhost ~]# ls
anaconda-ks.cfg install.log install.log.syslog longzls
[root@localhost ~]# zip longzls.zip longzls(空文件,所以压缩0%)
adding: longzls (stored 0%)
[root@localhost ~]# ls
anaconda-ks.cfg install.log install.log.syslog longzls longzls.zip
[root@localhost ~]#
注意:后缀不能缺少,不是因为系统原因,毕竟linux不区分后缀名,但是为了方便管理员管理不应该缺少
压缩文件是有个压缩格式的存储,如果源文件比较小,会发现压缩后文件反而更大,但是当你的压缩文件很大的时候,就会有比较好的效果
[root@localhost ~]# mkdir jp
[root@localhost ~]# ls
anaconda-ks.cfg install.log install.log.syslog jp longzls longzls.zip
[root@localhost ~]# touch jp/cangls
[root@localhost ~]# touch jp/longls
[root@localhost ~]# touch jp/bols
[root@localhost ~]# zip -r jp.zip jp
(2).zip格式解压缩
unzip压缩文件
#解压缩.zip文件
[root@localhost ~]# unzip jp.zip
(3).gz格式压缩
1).gzip 源文件
#压缩为.gz格式的压缩文件,源文件会消失
[root@localhost ~]# ls
anaconda-ks.cfg install.log install.log.syslog jp longzls
[root@localhost ~]# gzip longzls
[root@localhost ~]# ls
anaconda-ks.cfg install.log install.log.syslog jp longzls.gz
2).gzip -c 源文件 > 压缩文件
#-c是将文件内容输出,通过>指向输出位置,实现压缩,原文件也没有消失,如果没有目标,那么将直接输出到屏幕上,源文件消失
#压缩为.gz格式,原文件保留
例如:
gzip -c cangls > cangls.gz
3). gzip -r 目录
#压缩目录下所有的子文件,但是不能压缩目录
补充:.gz可以在windows中解压缩,但是.rar在linux不可以解压缩
[root@localhost ~]# gzip -r jp
[root@localhost ~]# ls
abc abc.gz anaconda-ks.cfg install.log install.long.syslog jp longzls.gz
[root@localhost ~]# cd jp/
[root@localhost jp]# ls
bols.gz cangls.gz longls.gz
压缩了目录下的子文件,但是没有压缩目录
(4).gz格式解压缩
gzip -d 压缩文件
#解压缩文件
gunzip 压缩文件
#解压缩文件
解压缩后,压缩文件会消失,源文件出现,而且解压缩目录时候同样不能缺少-r,即
gunzip -r 压缩文件
(5).bz2格式压缩
bzip2 源文件
#压缩为.bz2格式,不保留源文件
但是:bzip2 -k 源文件 (keep保留)
#压缩之后保留源文件
注意:bzip2命令不能压缩目录
(6).bz2格式解压缩
bzip2 -d 压缩文件
#解压缩,-k保留压缩文件
bunzip2 压缩文件
#解压缩,-k保留压缩文件
注意:bunzip2同样不能解压缩目录
(7).tar.gz,tar.bz2压缩格式
tar打包,先打包,再压缩
tar -cvf 打包文件名 源文件
选项:
-c:打包
-v:显示过程
-f:指定打包后的文件名
-t: test测试,不解压只查看
例如:
tar -cvf longzls.tar longzls
[root@localhost ~]# tar -cvf jp.tar jp
jp/
jp/bols
jp/longls
jp/cangls
[root@localhost ~]# gzip jp.tar
[root@localhost ~]# ls
abc abc.gz anaconda-ks.cfg install.log install.long.syslog jp jp.tar.gz
通过tar和gzip实现目录的压缩
tar.gz压缩格式:
其实.tar.gz格式是先打包为.tar格式,再压缩为.gz格式
tar -zcvf 压缩包名 .tar.gz 源文件
选项:
-z:压缩为.tar.gz格式

 tar -zxvf 压缩包名 .tar.gz 
选项:
-x: 解压缩.tar.gz格式

tar.bz2压缩格式:

同样.tar.bz2格式也是先打包为.tar格式,再压缩为.bz2格式
tar -jcvf 压缩包名 .tar.bz2 源文件
选项:
-j:压缩为.tar.bz2格式

  tar -jxvf 压缩包名 .tar.bz2 
选项:
-x: 解压缩.tar.bz2格式

注意前后压缩解压缩的格式一致性,不然会出错
(8).tar.gz,tar.bz2解压缩命令
tar –xvf 压缩包名.tar.gz/压缩包名.tar.bz2
选项:
-x:解包
-v:显示过程
-f:指定打包后的文件
-t: test测试,不解压只查看

!/bin/bash

cd /root/test

ls *.tar.gz > ls.log

ls *.tgz > ls.log

>覆盖,>>追加

列举出所有的压缩包,重定向到ls.log

for i in $(cat ls.log)

    do

tar –zxf $i $> /dev/null

/dev/null:所有的输出情况都不关注

    done

rm –rf /lamp/ls.log

删除临时文件

[root@localhost sh]# cd /root/test

[root@localhost tset]# ls

etc.tar.gz Python-3.4.3.tgz tmp.tar.gz

[root@localhost tset]# vi tar.sh

!/bin/bash

cd /root/test

ls *.tar.gz > ls.log

ls *.tgz >> ls.log

for i in $(cat ls.log)

      do

tar –zxf $i &> /dev/null

done

rm –rf /lamp/ls.log

~

[root@localhost tset]# chmod 755 tar.sh

[root@localhost tset]# ./tar.sh

[root@localhost tset]# ls

etc etc.tar.gz Python-3.4.3 Python-3.4.3.tgz tar_for.sh tmp tmp.tar.gz

解压缩成功

格式2:
for (( 初始值;循环控制条件;变量变化 ))

     do

程序

done

例子3:1+2+…+100:

!/bin/bash

计算从1加到100

s=0

for (( i=1;i<=100;i=i+1 ))

      do

s=$(( $s+$i ))

把s和i的数值按循环来依次叠加

     done

echo “The sum of 1+2+..+100 is: $s”

详细过程:

[root@localhost tset]# cd /root/sh/

[root@localhost sh]# vi for_sum.sh

!/bin/bash

s=0

for (( i=1;i<=100;i=i+1 ))

      do

s=$(( $s+$i ))

done

echo “$s”

~

wq

[root@localhost sh]# chmod 755 for_sum.sh

[root@localhost sh]# ./for_sum.sh

5050

例子4:批量添加指定数量的用户

!/bin/bash

批量添加到指定数量的用户

read –p “Please input user name:” –t 30 name

输入用户名,保存到name

read –p “Please input the number of users:” –t 30 num

输入用户数量,保存到num

read –p “Please input the password of users:” –t 30 pass

输入密码,保存到pass

if [ ! –z “ namea!z num” –a ! –z “$pass” ]

!:原始判断式取反;-z:判断字符串是否为空;-a:逻辑与and,全为真结果才为真

即判断这三个结果不为空

      then

y=$(echo $num | sed ‘s/[0-9]’)

判断num是否为纯数字,是则输出空值,

       if[ –z “$y”]

then

for (( i=1;i<=$num;i=i+1 ))

do

/usr/sbin/useradd $name$i &>/dev/null

echo $pass | /usr/bin/passwd - -stdin $name$i &>/dev/null

给name用户赋予pass密码

                    done

fi

fi

[root@localhost sh]# vi useradd.sh

!/bin/bash

read –p “Please input user name:” –t 30 name

read –p “Please input the number of users:” –t 30 num

read –p “Please input the password of users:” –t 30 pass

if [ ! –z “ namea!z num” –a ! –z “$pass” ]

      then

y=$(echo $num | sed ‘s/[0-9]’)

if[ –z “$y”]

then

for (( i=1;i<=$num;i=i+1 ))

do

/usr/sbin/useradd $name$i &>/dev/null

echo $pass | /usr/bin/passwd - -stdin $name$i &>/dev/null

done

fi

fi

~

wq

[root@localhost sh]# cat /etc/passwd

查看用户

[root@localhost sh]# chmod 755 useradd.sh

[root@localhost sh]# ./useradd.sh

Please input user name: DukeZ

Please input the number of users: 10

Please input the password of users: 123456

[root@localhost sh]# cat /etc/passwd

DukeZ1 :x: 520:520:: /home/DukeZ1: /bin/bash

..

DukeZ10 :x: 520:520:: /home/DukeZ10: /bin/bash

思考:批量删除用户
提取出所用用户的用户名,通过登录用户bash来区分登录用户和伪用户

[root@localhost sh]# cat /etc/passwd | grep /bin/bash | grep –v root | cut –d “:”-f1

[root@localhost sh]# vi userdel.sh

!/bin/bash

user=$( cat /etc/passwd | grep /bin/bash | grep –v root |cut –d “:” -f1)

for i in $user

   do

userdel –f $i

done

~

wq

[root@localhost sh]# chmod 755 userdel.sh

[root@localhost sh]# ./userdel,sh

[root@localhost sh]# cat /etc/passwd

删除DukeZ1-DukeZ10成功

七、while循环和until循环

有if,case,for,怎么可以少了while,until

1.while循环

while循环是不定循环,也称条件循环,只要条件判断式成立,循环就会一直继续,条件没有设置好就容易出现死循环,直到条件判断式不成立,循环就会终止,这和for的固定循环不太一样

格式:
while [ 条件判断式 ]

  do

程序

done

详细实例:从1加到100

!/bin/bash

i=1

s=0

while [ $i –le 100]

如果变量i的值小于100,则执行循环

         do

s=$(( $s+$i ))

i=$(( $i+1 ))

done

echo “The sum is : $s”

2.until循环

until循环,和while循环相反,until循环时只要条件判断式不成立就进行循环,并执行循环程序。一弹循环条件成立,则终止循环

格式:
until [ 条件判断式 ]

  do

程序

done

详细实例:从1加到100

!/bin/bash

i=1

s=0

while [ $i –gt 100]

如果变量i的值大于于100,则终止循环

         do

s=$(( $s+$i ))

i=$(( $i+1 ))

done

echo “The sum is : $s”

[root@localhost sh]# vi until.sh

!/bin/bash

i=1

s=0

while [ $i –le 100]

         do

s=$(( $s+$i ))

i=$(( $i+1 ))

done

echo “The sum is : $s”

~

wq

[root@localhost sh]# chmod 755 until.sh

[root@localhost sh]# ./until.sh

The sum is : 5050

八、总结

注意Shell主要是用来简化管理员操作的,考虑的更多的是功能的实现,而不是代码语法和算法的复杂