2018-07-26 第三十一次课

Posted minn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018-07-26 第三十一次课相关的知识,希望对你有一定的参考价值。

第三十一次课 shell编程

目录

一、shell脚本介绍
二、shell脚本结构和执行
三、date命令用法
四、shell脚本中的变量
五、hell脚本中的逻辑判断
六、文件目录属性判断
七、if特殊用法
八、case判断
九、for循环
十、while循环
十一、break跳出循环
十二、continue结束本次循环
十三、exit退出整个脚本
十四、扩展


一、shell脚本介绍

shell是一种脚本语言, 是用户与内核进行交互的一种接口。

shell可以使用逻辑判断、循环等语法,也可以自定义函数。

shell是系统命令的集合

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


二、shell脚本结构和执行

shell脚本通常在编辑器中编写,由命令及其注释组成,注释是跟在#号后的内容,用来对脚本进行解释。

第一行 位于脚本左上角的第一行会指出由哪个程序来执行脚本中的行。这一行通常称为shbang,写作#!/bin/bash

一个bash shell程序由一组unix/linux命令、bash命令、程序结构控制语句和注释组成

为便于区分,一般以.sh结尾。

例如:

#!/bin/bash
# Scriptname: greet
for name in $*        # same as for name in [email protected]
do
    echo Hi $name  
done

shell的执行方式有二种

  • chmod u+x greet.sh; ./sh 或绝绝对路径执行
  • bash greet.sh
//执行方式1
[[email protected] sh]# vim greet.sh
[[email protected] sh]# chmod u+x greet.sh
[[email protected] sh]# ./greet.sh kennminn
Hi kennminn
或者
[[email protected] sh]# chmod u+x greet.sh
[[email protected] sh]# pwd
/root/script/sh
[[email protected] sh]# /root/script/sh/greet.sh kennminn
Hi kennminn

//执行方式2
[[email protected] sh]# bash greet.sh kennminn
Hi kennminn

查看脚本的执行过程 bash -x script-name

[[email protected] sh]# bash -x greet.sh kennminn
+ for name in ‘$*‘
+ echo Hi kennminn
Hi kennminn

查看脚本是否有语法错误

//没有语法错误时
[[email protected] sh]# bash -n greet.sh kennminn
//将最后一行的done删掉
[[email protected] sh]# vim greet.sh 
#!/bin/bash
# Scriptname: greet
for name in $*        # same as for name in [email protected]
do
        echo Hi $name  

[[email protected] sh]# bash -n greet.sh kennminn
greet.sh: line 7: syntax error: unexpected end of file


三、date命令用法

date命令打印系统日期和时间。

[[email protected] sh]# date 
Sun Jul 29 21:08:24 EDT 2018

常用格式

命令 含义
date +%Y 年(4位)
date +%y 年(2位)
date +%m
date +%d
date +%D 以月/日/年格式显示日期
date +%F 以年-月-日格式显示日期
date +%H 小时
date +%M 分钟
date +%S
date +%T 以时:分:秒格式显示时间,等于date +%H:%M:%S
date +%s 时间戳表示距离1970年1月1日到现的秒数
date +%w 这个星期的第几周
date +%W 今年的第几周
date +%h 月份缩写,等于date +%b
date -d "-1 day" 一天前
date -d "+1 day" 一天后
date -d "-1 year" 一年前
date -d "-1 month" 一个月前
date -d "-1 hour" 一小时前
date -d "-1 min" 一分钟前

eg:

//显示日期
[[email protected] sh]# date +%Y-%m-%d
2018-07-29
[[email protected] sh]# date +%F
2018-07-29
[[email protected] sh]# date +%D
07/29/18
//显示时间
[[email protected] sh]# date +%H:%M:%S
09:22:23
[[email protected] sh]# date +%T
09:22:30
//显示时间戳
[[email protected] sh]# date +%s
1532913790
//显示1天后的日期
[[email protected] sh]# date -d "+1 day"
Tue Jul 31 09:24:16 CST 2018
//显示1天前的日期
[[email protected] sh]# date -d "-1 day" 
Sun Jul 29 09:24:43 CST 2018
//显示1小时前的时间
[[email protected] sh]# date -d "-1 hour" +%T
08:25:43
//将时间戳以日期格式显示
[[email protected] sh]# date -d @1532913790
Mon Jul 30 09:23:10 CST 2018
//显示指定日期的时间戳
[[email protected] sh]# date +%s -d "2018-06-23"
1529683200
//显示日历
[[email protected] sh]# cal
      July 2018     
Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
//显示指定月的日历
[[email protected] sh]# cal 7 17
       July 17      
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31


四、shell脚本中的变量

变量就是为某个信息片段所起的名字,标志内存中的一段地址。

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

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

引用某个命令的结果时,用变量替代   n=wc -l 1.txt 或者n=$(wc -l 1.txt)

写和用户交互的脚本时,变量也是必不可少的  read -p "Input a number: " n; echo $n   如果没有指定变量名n,默认变量名为REPLY

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

$*表示获取当前shell脚本所有传参的个数,不加引号和[email protected]相同,加上引号则将所有的参数视为单个字符串。相当于”$1 $2 $3”。

[email protected]表示获取当前shell脚本所有传参的参数,不加引号和$*相同。如果给[email protected]加上双引号,例如”[email protected]”,则表示将所有的参数视为不同的独立字符串,相当于”$1”,”$2”,”$3”….这是将多参数传递给其他程序的最佳方式,因为它会保留所有的内嵌在每个参数里的任何空白。当”[email protected]”和”$*”都加双引号时,两者是有区别的,都不加双引号,两者无区别。

变量有环境变量和用户自定义变量

用户自定义变量变量名可以由一个字母、数字或下划线符号组成,不能以数字开头。长度不超过20个字符。变量名区分大小写,请留意:Var1 和var1不是同一个变量。

例如:

//等号(=)两端不能有空格
//引用变量值的方式:在变量名前加$
[[email protected] sh]# name=terry
[[email protected] sh]# echo $name
terry
[[email protected] sh]# name =terry
-bash: name: command not found

shell中只能进行整数运行,如果需要进行浮点数,需要借助bc命令

整数运算语法

1.$[ ]

[[email protected] sh]# n=5;echo $[$n+1]
6

2.$(())

[[email protected] sh]# n=5;echo $(($n+1))
6
[[email protected] sh]# n=5;echo $((n+1))
6

3.(())

[[email protected] sh]# ((n+=1));echo $n
6

4.expr

//注意+号两边要有空格
[[email protected] sh]# expr 4 + 5
9

[[email protected] sh]# r=`expr 4 + 5`
[[email protected] sh]# echo $r
9

5.let

[[email protected] sh]# let n=n+1
[[email protected] sh]# echo $n
1


五、hell脚本中的逻辑判断

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

[[email protected] sh]# vim if1.sh
#!/bin/bash

a=3

if [ $a -gt 2 ]
then
    echo ok!
fi

[[email protected] sh]# chmod u+x if1.sh 
[[email protected] sh]# ./if1.sh  
ok!

或者
[[email protected] sh]# a=3;if [ $a -gt 2 ]; then echo ok! ; fi
ok!

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

[[email protected] sh]# vim if2.sh
#!/bin/bash

a=1

if [ $a -gt 2 ]
then
        echo ok!
else
        echo It‘s no ok!
fi

[[email protected] sh]# ./if2.sh  
It‘s no ok!

[[email protected] sh]# sh -x ./if2.sh 
+ a=1
+ ‘[‘ 1 -gt 2 ‘]‘
+ echo ‘It‘‘‘s‘ no ‘ok!‘
It‘s no ok!

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

[[email protected] sh]# vim if3.sh   
#/bin/bash

a=2

if [ $a -eq 3 ];then
    echo The number is three.
elif [ $a -gt 3 ];then
    echo the number is great then three.
else
    echo the number is less then three.
fi

[[email protected] sh]# chmod u+x if3.sh
[[email protected] sh]# ./if3.sh        
the number is less then three.

[[email protected] sh]# sh -x ./if3.sh 
+ a=2
+ ‘[‘ 2 -eq 3 ‘]‘
+ ‘[‘ 2 -gt 3 ‘]‘
+ echo the number is less then three.
the number is less then three.

test命令的数值比较功能

比较 描述
n1 -eq n2 检查n1是否等于n2
n1 -ge n2 检查n1是否大于等于n2
n1 -gt n2 检查n1是否大于n2
n1 -le n2 检查n1是否小于等于n2
n1 -lt n2 检查n1是否小于n2
n1 -ne n2 检查n1是否不等于n2

test命令的字符串比较

比较 描述
str1 = str2 检查str1和str2是否相等
str1 != str2 检查str1和str2是否不相等
str1 < str2 检查str1是否比str2小
str1 > str2 检查str1是否比str2大

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

if [ $a -gt 5 ] && [ $a -lt 10 ] &&表示并且

if [ $b -gt 5 ] || [ $b -lt 3 ] ||表示或者


六、文件目录属性判断

文件比较

比较 描述
-d file 检查文件是否存且是一个目录
-e file 检查文件是否存在
-f file 检查文件是否存且是一个文件
-r file 检查文件是否存在且可读
-s file 检查文件是否存在且非空
-w file 检查文件是否存在并可写
-x file 检查文件是否存在并可执行
-o file 检查文件是否存在并属当前用户所有
-G file 检查文件是否存在并且默认组与当前用户相同
file1 -nt file2 检查file1是否比file2新
file1 -ot file2 检查file1是否比file2旧
[[email protected] sh]# vim file1.sh
#/bin/bash

f1=‘/tmp/tt.txt‘

if [ -f $f1 ];then
    echo "$f exist"
else
    touch $f1
fi

//第一次文件不存在时
[[email protected] sh]# sh -x file1.sh 
+ f1=/tmp/tt.txt
+ ‘[‘ -f /tmp/tt.txt ‘]‘
+ touch /tmp/tt.txt

//第二次文件已经存在
[[email protected] sh]# sh -x file1.sh 
+ f1=/tmp/tt.txt
+ ‘[‘ -f /tmp/tt.txt ‘]‘
+ echo ‘ exist‘
 exist
 
//判断文件目录是否存在
[[email protected] sh]# cp file1.sh file2.sh     
[[email protected] sh]# vim file2.sh 
#/bin/bash

f1=‘/tmp/tt.txt‘

if [ -f $f1 ];then
    echo "$f exist"
fi

[[email protected] sh]# ./file2.sh 
 exist
 
//判断文件是否可读
[[email protected] sh]# cp file2.sh file3.sh
[[email protected] sh]# vim file3.sh 

#/bin/bash

f1=‘/tmp/tt.txt‘

if [ -r $f1 ];then
        echo "$f is readable"
fi

[[email protected] sh]# ./file3.sh     
 is readable
 


七、if特殊用法

比较 描述
-n str2 检查str1的长度是否非0
-z str2 检查str1的长度是否为0
[[email protected] sh]# vim file4.sh
#!/bin/bash

file=‘/tmp/tt.txt‘

if [ -n "$file" ];then
    echo "the file  $file is not empty"
fi

[[email protected] sh]# ./file4.sh   
the file  /tmp/tt.txt is empty

其他特殊用法

使用命令来做判断条件

//-q表示静默模式
//grep命令匹配其返回值是0,如果没有匹配则返回值是非0
[[email protected] sh]# if grep -q ‘hjm‘ /etc/passwd;then echo user exist;fi
user exist

使用! 在参数前 表示取反 [ ! -e file ] 表示文件不存在

中括号中不能使用<,>,==,!=,>=,<=这样的符号


八、case判断

语法:

case  变量名 in 
    value1)
        command
        ;;
    value2)
        command
        ;;
    *)
        commond
        ;;
    esac

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

a|b) 
    command
    ;;

eg

[[email protected] shell]# vim case1.sh

#!/bin/bash
read -p "Please input number: " n
#让用户输入数字
if [ -z "$n" ]
then
        echo "Please input number: "
        exit 1
fi
#判断用户是否没填数字
n1=`echo $n|sed ‘s/[0-9]//g‘`
if [ ! -z "$n1" ]
then
        echo "Please input number: "
        exit 1
fi
#判断用户是否填纯数字
if [ $n -lt 60 ]
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
#给分数赋值给tag
case $tag in
        1)
        echo "bu ji he"
        ;;
        2)
        echo "liang hao"
        ;;
        3)
        echo "you xiu"
        ;;
        4)
        echo "fei chang bang"
        ;;
        *)
        echo "The number range is 0-100"
        ;;
esac

[[email protected] sh]# vim grade.sh
[[email protected] sh]# sh -x ./grade.sh    
+ read -p ‘Please input number: ‘ n
Please input number: 60
+ ‘[‘ -z 60 ‘]‘
++ echo 60
++ sed ‘s/[0-9]//g‘
+ n1=
+ ‘[‘ ‘!‘ -z ‘‘ ‘]‘
+ ‘[‘ 60 -lt 60 ‘]‘
+ ‘[‘ 60 -ge 60 ‘]‘
+ ‘[‘ 60 -lt 80 ‘]‘
+ tag=2
+ case $tag in
+ echo ‘liang hao‘
liang hao


九、for循环

语法格式

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

eg

//计算1到100的和
[[email protected] sh]# vim sum.sh
#!/bin/bash

result=0
for i in $(seq 1 100)
do
    result=$((result+i))
done
echo $result

[[email protected] sh]# chmod u+x sum.sh 
[[email protected] sh]# ./sum.sh 
5050

//遍历/etc目录并把目录列出来
[[email protected] sh]# vim for2.sh
#!/bin/bash

cd /etc

for file in *
do
    [ -d $file ] && ls $file
done

[[email protected] sh]# chmod u+x for2.sh 
[[email protected] sh]# ./for2.sh | more
abrt-action-save-package-data.conf
abrt.conf
gpg_keys.conf
plugins
ld
libnssckbi.so.x86_64
mta
mta-aliasesman
...下略


十、while循环

语法格式

while 条件; do … ; done

eg

//每隔30秒查看系统负载,当大于10时发邮件
[[email protected] sh]# vim while1.sh
#!/bin/bash
while :
do
        load=`w|head -1|awk -F ‘load average: ‘ ‘{print $2}‘|cut -d . -f1`
        if [ $load -gt 10 ]
        then
                /usr/local/sbin/mail.py [email protected] "load high" "$load"
        fi
        sleep 30
done

[[email protected] sh]# chmod u+x while1.sh 
[[email protected] sh]# sh -x while1.sh 
+ :
++ w
++ cut -d . -f1
++ awk -F ‘load average: ‘ ‘{print $2}‘
++ head -1
+ load=0
+ ‘[‘ 0 -gt 10 ‘]‘
+ sleep 30

: ture 1 都是代表为正 因此while : 就是一个死循环
为了不让while脚本不意外终止 可以使用screen命令 再到screen下执行此脚本

//提示让用户只能输入数字
[[email protected] sh]# vim while2.sh
#!/bin/bash
while :
do
        read -p "Please input a number: " n
        if [ -z "$n" ]
        then
        echo "Please input sth!"
        continue
        fi
##判断用户是否直接回车
        n1=`echo $n|sed ‘s/[0-9]//g‘`
        if [ -n "$n1" ]
        then
        echo "Please input number!"
        continue
        fi
#判断用户是否输入纯数字
echo $n
break
done

[[email protected] sh]# sh while2.sh 
Please input a number: a        
Please input number!
Please input a number: v
Please input number!
Please input a number: 1
1

echo $n|sed ‘s/[0-9]//g 把数字替换为空,再来判断剩下的内容


十一、break跳出循环

eg

[[email protected] shell]# vim break.sh

#!/bin/bash
for i in $(seq 1 5)
do
        echo $i
        if [ $i -eq 3 ]
        then
            break
        fi
        echo $i
done
echo aaaa

[[email protected] sh]# chmod u+x break.sh 
[[email protected] sh]# ./break.sh 
[[email protected] sh]# ./break.sh  
1
1
2
2
3
aaaa


十二、continue结束本次循环

忽略本次循环,直接进行下一次循环

eg

[[email protected] sh]# mv break.sh continue.sh
[[email protected] sh]# vim continue.sh 
#!/bin/bash
for i in $(seq 1 5)
do
        echo $i
        if [ $i -eq 3 ]
        then
            continue
        fi
        echo $i
done
echo aaaa

[[email protected] sh]# ./continue.sh 
1
1
2
2
3
4
4
5
5
aaaa


十三、exit退出整个脚本

eg

[[email protected] sh]# mv continue.sh exit.sh
[[email protected] sh]# vim exit.sh 
#!/bin/bash
for i in $(seq 1 5)
do
        echo $i
        if [ $i -eq 3 ]
        then
            exit 1
        fi
        echo $i
done
echo aaaa

[[email protected] sh]# ./exit.sh 
1
1
2
2
3

总结:

break,continue都是在for while循环中使用的

break出现时候会跳出本次循环 直接忽略掉了break后面的代码

continue出现时候也会忽略掉了continue后面的代码并重新再来执行循环

exit直接跳出脚本 一般exit 后面会跟一个数字 给用户返回该值


十四、扩展

select用法

http://www.apelearn.com/bbs/thread-7950-1-1.html




























以上是关于2018-07-26 第三十一次课的主要内容,如果未能解决你的问题,请参考以下文章

python学习第三十一节

开始写游戏 --- 第三十一篇

学习三十一

WPF学习第三十一章 WPF命令模型

2018-09-08 第四十四十一次课

小刘同学的第三十一篇博文