第二十章、shell 编程(上)

20.1 shell脚本介绍

20.2 shell脚本结构和执行

20.3 date命令用法

20.4 shell脚本中的变量

20.5 shell脚本中的逻辑判断

20.6 文件目录属性判断

20.7 if特殊用法

20.8/20.9 case判断

20.10 for循环

20.11/20.12 while循环

20.13 break跳出循环

20.14 continue结束本次循环

20.15 exit退出整个脚本

20.1 shell脚本介绍

shell是一种脚本语言  

#阿铭博客有大量shell习题

 blog.lishiming.net

可以使用逻辑判断、循环等语法

可以自定义函数

shell是系统命令的集合

shell脚本可以实现自动化运维,能大大增加我们的运维效率

20.2 shell脚本结构和执行

一、shell脚本结构

  • 开头需要加#!/bin/bash(文件头指定接下来运行命令是通过哪个解释器操作的)

  • 以#开头的行作为解释说明(除了文件头)

  • 脚本的名字以.sh结尾,用于区分这是一个shell脚本

二、执行方法有两种

第一种:需要增加运行权限才行

chmod a+x 1.sh;

 ./1.sh             #当前路径下,也可写绝对路径

[root@xinlinux-03 shell]# ./1.sh

-bash: ./1.sh: 权限不够

[root@xinlinux-03 shell]# chmod a+x 1.sh

[root@xinlinux-03 shell]# ./1.sh

123

第二种:

bash 1.sh 或者sh  1.sh

[root@xinlinux-03 shell]# sh 1.sh

123

[root@xinlinux-03 shell]# bash 1.sh

123

三、查看脚本

bash -x 1.sh        #查看脚本执行过程

[root@xinlinux-03 shell]# bash -x 1.sh

+ echo 123

123

bash -n 1.sh       #查看脚本是否语法错误(如果命令写错是检测不出来的)

20.3 date命令用法

date  +%Y-%m-%d 等同于 date  +%F #年月日

[root@xinlinux-03 shell]# date  +%Y-%m-%d

2018-10-23

date +%y-%m-%d  #年月日

[root@xinlinux-03 shell]# date +%y-%m-%d

18-10-23

年月日

#%Y是年的4位数,2017;%y年是最后2位,17;%m是月份,%M是分钟;%d是日期,%D是显示年月日,例如:09/09/17;%F是显示年月日带横杠,例如:2017-09-09;

[root@xinlinux-03 shell]# date +%M

55

[root@xinlinux-03 shell]# date

2018年 10月 23日 星期二 08:55:35 CST

[root@xinlinux-03 shell]# date +%d

23

[root@xinlinux-03 shell]# date +%D

10/23/18

[root@xinlinux-03 shell]# date +%F

2018-10-23

时分秒

#%H是小时,%h是英文的月份;%s是时间戳(距离1970年1月日1点距离现在多少秒);%S是秒;%T是显示时间,例如:06:47:12

date  +%H:%M:%S =  date +%T   #时间

[root@xinlinux-03 shell]# date  +%H:%M:%S

08:57:20

[root@xinlinux-03 shell]# date +%T

08:57:25

%w是星期几;%W是今年的第几周;

date +%w, date +%W   #星期

[root@xinlinux-03 shell]# date

2018年 10月 23日 星期二 08:57:50 CST

[root@xinlinux-03 shell]# date +%w

2

[root@xinlinux-03 shell]# date +%W

43

cal      #显示日历查看日期

时间戳

date +%s      #查看当前时间下的时间戳

date +%s  -d "2018-10-23 09:03:06"     #通过完整的时间查看该时间的时间戳

date -d @1540256586        #通过时间戳查看该时间戳的完整时间

[root@xinlinux-03 shell]# date

2018年 10月 23日 星期二 09:03:06 CST

[root@xinlinux-03 shell]# date +%s  -d "2018-10-23 09:03:06"

1540256586

[root@xinlinux-03 shell]# date -d @1540256586

2018年 10月 23日 星期二 09:03:06 CST

标记日期方式

date -d "+1day"       #一天后

date -d "-1 day"       #一天前

date -d "-1 month"  #一月前

date -d "-1 min"      #一分钟前

[root@xinlinux-03 shell]# date -d "+1 day"

2018年 10月 24日 星期三 09:05:14 CST

[root@xinlinux-03 shell]# date -d "-1 day"

2018年 10月 22日 星期一 09:05:20 CST

[root@xinlinux-03 shell]# date -d "-1 month"

2018年 09月 23日 星期日 09:05:27 CST

[root@xinlinux-03 shell]# date -d "-1 min"

2018年 10月 23日 星期二 09:04:38 CST

date -d "-1 day"  +%F    #显示一天前的时间   

[root@xinlinux-03 shell]# date -d "-1 day"  +%F

2018-10-22

20.4 shell脚本中的变量

#当脚本中使用某个字符串较频繁并且字符串长度很长时就应该使用变量代替

  • 使用条件语句时,常使用变量    if [ $a -gt 1 ]; then ... ; fi

  • 引用某个命令的结果时,用变量替代   n=`wc -l 1.txt`

  • 写和用户交互的脚本时,变量也是必不可少的  read -p "Input a number: " n; echo $n   如果没写这个n,可以直接使用$REPLY

  • 内置变量 $0, $1, $2…    $0表示脚本本身,$1 第一个参数,$2 第二个 ....       $#表示参数个数

  • 数学运算a=1;b=2; c=$(($a+$b))或者$[$a+$b]

20.5 shell脚本中的逻辑判断

格式1:if 条件 ; then 语句; fi

vim if.sh

#!/bin/bash

a=5

if [ $a -gt 3 ]

then

    echo "ok"

fi

#如果a大于3,就输出ok

[root@xinlinux-03 shell]# bash -x if.sh

+ a=5

+ '[' 5 -gt 3 ']'

+ echo ok

ok

格式2:if 条件; then 语句; else 语句; fi

vim  if.sh

#!/bin/bash

a=2

if [ $a -gt 3 ]

then

    echo "ok"

else

    echo "nook"

fi

# 如果a大于3,就输出ok,反之否则就输出nook

[root@xinlinux-03 shell]# bash -x if.sh

+ a=2

+ '[' 2 -gt 3 ']'

+ echo nook

nook

格式3:if …; then … ;elif …; then …; else …; fi

####elif是一逻辑条件判断,elif等同于else  if

vim if.sh

#!/bin/bash

a=5

if [ $a -lt 4 ]

then

    echo "<4"

elif [ $a -lt 6 ]

then

    echo "<6  &&  <4"

else

    echo "nook"

fi

#如果a小于4,就输出<4;否则继续判断a是否小于6,是的话输出<6  &&  >4,否则输出nook

[root@xinlinux-03 shell]# bash -x if.sh

+ a=5

+ '[' 5 -lt 4 ']'

+ '[' 5 -lt 6 ']'

+ echo '<6  &&  <4'

<6  &&  <4

逻辑判断表达式:if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等

## -gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=)     #注意到处都是空格

#可以使用 && || 结合多个条件

if [ $a -gt 5 ] && [ $a -lt 10 ]; then

#当a大于5且小于10,就输出

if [ $b -gt 5 ] || [ $b -lt 3 ]; then

#当a大于5或者小于10,就输出

20.6 文件目录属性判断

if 判断文件、目录属性

[ -f file ]判断是否是普通文件,且存在

[ -d file ] 判断是否是目录,且存在

[ -e file ] 判断文件或目录是否存在

vim if1.sh

#!/bin/bash

f="/tmp/aminglinux"

if [ -f   $f  ]

then 

    echo $f  exist

else

    touch $f

fi

#判断f是否文普通文件且存在,如果正确输出file exist;否则创建该文件touch file

[root@xinlinux-03 shell]# bash -x if1.sh

+ f=/tmp/aminglinux

+ '[' -f /tmp/aminglinux ']'

+ touch /tmp/aminglinux

[root@xinlinux-03 shell]# bash -x if1.sh

+ f=/tmp/aminglinux

+ '[' -f /tmp/aminglinux ']'

+ echo /tmp/aminglinux exist

/tmp/aminglinux exist

[ -r file ] 判断文件是否可读

[ -w file ] 判断文件是否可写

[ -x file ] 判断文件是否可执行

20.7 if特殊用法

一、判断变量是否为空

if [ -z "$a" ]  这个表示当变量a的值为空时会怎么样

if [ -n "$a" ] 表示当变量a的值不为空

#这两条if的$a要加上双引号"",因为是变量,如果是文件名就不用双引号

二、使用命令的结果作为判断

if grep -q '123' 1.txt; then  表示如果1.txt中含有'123'的行时会怎么样

#grep -q,表示只将需要的内容过滤但并不会显示出来

三、在选项前面加!取反

if [ ! -e file ]; then 表示文件不存在时会怎么样

四、将方括号[]换成小括号()可用<,>,==,!=,>=,<=

if (($a<1)); then … 等同于 if [ $a -lt 1 ]; then…

###[ ] 中不能使用<,>,==,!=,>=,<=这样的符号

20.8/20.9 case判断

格式: 

#value指的是参数值;command是具体命令;双分号";;"表示这个判断结束

        case  变量名 in

                     value1)

                          command

                          ;;

                     value2)

                          command

                          ;;

                      *)

                        commond

                            ;;

                      esac

#在case程序中,可以在条件中使用|,表示或的意思, 比如    

2|3)

    command

    ;;

shell脚本案例

输入数字,判断分数的级别

vim case.sh

#!/bin/bash

read -p "Please input a number: " n

#read -p,让用户输入内容为变量n的值,然后捕获内容

if [ -z "$n" ]

then

    echo "Please input a number."

    exit 1

fi

#if判断用户输入是否为空,如果为空,则exit 1,返回退出

n1=`echo $n|sed 's/[0-9]//g'`

#将$n内容的数字全部置空后的值变为n1变量

if [ -n "$n1" ]

then

echo "Please input a number."

exit 1

fi

#if判断n1是否不为空,是的话exit 1返回退出

#n1和if的目的是让用户输入纯数字

if [ $n -lt 60 ] && [ $n -ge 0 ]

then

    tag=1

elif [ $n -ge 60 ] && [ $n -lt 80 ]

then

    tag=2

elif [ $n -ge 80 ]  && [ $n -lt 90 ]

then

    tag=3

elif [ $n -ge 90 ] && [ $n -le 100 ]

then

    tag=4

else

    tag=0

fi

#if判断分数,输出tag级别

case $tag in

    1)

  echo "not ok"

        ;;

    2)

        echo "ok"

        ;;

    3)

        echo "ook"

        ;;

    4)

        echo "oook"

        ;;

    *)

        echo "The number range is 0-100."

        ;;

# 通过case判断tag级别的数值参数选择对应的命令执行

# *)表示除此之外的参数

esac

#esac结束

[root@xinlinux-03 shell]# bash -x case.sh

+ read -p 'Please input a number: ' n

Please input a number: 60

+ '[' -z 60 ']'

++ echo 60

++ sed 's/[0-9]//g'

+ n1=

+ '[' -n '' ']'

+ '[' 60 -lt 60 ']'

+ '[' 60 -ge 60 ']'

+ '[' 60 -lt 80 ']'

+ tag=2

+ case $tag in

+ echo ok

ok

 20.10 for循环

语法:

for 变量名 in 条件; do …; done

案例1

计算1到100的和

vim for.sh

#!/bin/bash

sum=0

for i in `seq 1 100`

do

    sum=$[$sum+$i]

    echo $i

done

echo $sum

[root@xinlinux-03 shell]# bash -x for.sh

+ sum=0

++ seq 1 100

+ for i in '`seq 1 100`'

+ sum=1

+ echo 1

1

+ for i in '`seq 1 100`'

+ sum=3

+ echo 2

2

.....

100

+ echo 5050

5050

案例2

文件列表循环查看

vim for2.sh

#!/bin/bash

cd /etc/

for a in `ls /etc/`

do

    if [ -d $a ]

    then

       ls -d $a

    fi

done

[root@xinlinux-03 shell]# bash -x for2.sh

+ cd /etc/

++ ls /etc/

+ for a in '`ls /etc/`'

+ '[' -d adjtime ']'

+ for a in '`ls /etc/`'

+ '[' -d aliases ']'

for 变量名 in ` 对象 `

#对象如果是查看命令,则命令后的所有结果会一个个匹配,例如:

for i in `seq 1 3`;do echo $i; done

[root@xinlinux-03 shell]# for i in `seq 1 3`;do echo $i; done

1

2

3

#对象也可是具体的数值,例如:

for i in 1 2 3 ;do echo $i; done

[root@xinlinux-03 shell]# for i in 1 2 3 ;do echo $i; done

1

2

3

#for循环时会以空格为分隔符

举一个错误实例

touch 1 2            #创建两个文件,分别是2 ,3 

touch 3\ 4.txt     #这个是一个文件3 4.txt

ll

[root@xinlinux-03 123]# ll

总用量 0

-rw-r--r-- 1 root root 0 10月 23 09:21 1

-rw-r--r-- 1 root root 0 10月 23 09:21 2

-rw-r--r-- 1 root root 0 10月 23 09:21 3 4.txt

for i in `ls ./`;do echo $i; done

#for循环将3 4.txt拆分成两个文件3,4.txt

 [root@xinlinux-03 123]# for i in `ls ./`;do echo $i; done

1

2

3

4.txt

#从实验结果可以知道3 4.txt文件被分成了两个文件3,4.txt

20.11/20.12 while循环

语法 while 条件; do … ; done

案例1

每分钟检查系统的负载,average大于10的时候发一封邮件

vim while1.sh

#!/bin/bash

while :

#此处的冒号":"与true是一样的效果,该脚本变成死循环脚本

do

    load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`

#赋值load为1分钟系统负载数

    if [ $load -gt 10 ]

    then

            /usr/local/sbin/mail.py [email protected]  "load is high: $load" 

    fi

#if判断load大于10就发送邮件

    sleep 30

#30秒间隔一次查看系统负载

done

案例2

人为交互输入数字

vim while2.sh

#!/bin/bash

while :

do

    read -p "Please input a number: " n

    if [ -z "$n" ]

    then

        echo "you need input sth."

        continue

    fi

#if判断n是否为空,如果是空,continue继续再来一遍循环

    n1=`echo $n|sed 's/[0-9]//g'`

    if [ -n "$n1" ]

    then

        echo "you just only input numbers."

        continue

    fi

#if判断n1是否不为空,如果不为空(不是纯数字),continue继续再来一遍循环

    break

#跳出while循环

done

echo $n

[root@xinlinux-03 shell]# bash -x while2.sh

+ :

+ read -p 'Please input a number: ' n

Please input a number: lp6+

+ '[' -z lp6+ ']'

++ echo lp6+

++ sed 's/[0-9]//g'

+ n1=lp+

+ '[' -n lp+ ']'

+ echo 'you just only input numbers.'

you just only input numbers.

+ continue

+ :

+ read -p 'Please input a number: ' n

Please input a number: 123

+ '[' -z 123 ']'

++ echo 123

++ sed 's/[0-9]//g'

+ n1=

+ '[' -n '' ']'

+ break

+ echo 123

123

20.13 break跳出循环

vim break.sh

#!/bin/bash

for i in `seq 1 5`

do

    echo $i

    if [ $i == 3 ] 

#只有当值是数字的时候才能用==,一般情况最正确的用法是用-eq

    then

        break

#此处break跳出for循环

    fi

    echo $i

done

echo aaaaaaa

[root@xinlinux-03 shell]# bash  break.sh

1

1

2

2

3

aaaaaaa

20.14 continue结束本次循环

#忽略continue之后的代码,直接进行下一次循环

vim continue.sh

#!/bin/bash

for i in `seq 1 5`

do

    echo $i

    if [ $i == 3 ]

    then

        continue

#结束i=3的for循环,后面的echo $i被忽略,直接进行下一次i=4的循环

    fi

    echo $i

done

echo aaaaaaa

[root@xinlinux-03 shell]# bash continue.sh

1

1

2

2

3

4

4

5

5

aaaaaaa

20.15 exit退出整个脚本

vim exit.sh

#!/bin/bash

for i in `seq 1 5`

do

    echo $i

    if [ $i == 3 ]

    then

        exit

#直接退出整个脚本

    fi

    echo $i

done

echo aaaaaaa

[root@xinlinux-03 shell]# bash exit.sh

1

1

2

2

3

猜你喜欢

转载自blog.csdn.net/Lucky_LGX/article/details/87978140