shell脚本编程详解

    脚本编程是一种编程能力的体现。

    编程语言分为以下几类:

        1,机器语言

        2,汇编语言

        3,高级语言:

            (1)静态语言:编译型语言->强类型语言

               强类型语言指的是变量的类型在程序执行前声明好,不能在程序执行过程中随意改变变量类型的语言,强类型语言常见的有:C、C++、Java、C#等,编译型语言在程序执行前会依靠编译器将程序全部转换成可执行的二进制格式,编译型语言需要事先确定好变量类型,因为它没有解释器,解释器的机制可以帮助程序自动声明变量的类型,强类型的语言,变量在使用前必须进行声明,甚至还要进行初始化,数值初始化为0,字符初始化为空,0不是空,空是null->什么都没有。

            (2)动态语言:解释型语言->弱类型语言

               弱类型语言指的是变量的类型不需要在程序执行前声明,可以在程序执行的过程中根据需求改变变量的类型的语言,弱类型语言常见的有:php、shell、python、perl等,解释型语言是边解释边执行,执行特性称为on the fly,解释型语言需要一个解释器,解释器通常为静态语言开发。解释器通常的讲就相当于是人与计算机之间沟通的一个翻译官,使用解释器还是编译器是根据语言的类型来定的,弱类型的语言变量在使用时声明即可,甚至可以不区分类型,默认为字符串,弱类型的变量类型转换分为显式转换和隐式转换,shell为弱类型的编程语言。

            高级语言也可以这么分类:

                (1)面向过程语言:shell脚本、C语言等。

                (2)面向对象语言:Java、Python、perl、C++等。


·变量

     ->是一段被命名了的内存空间。

     ->内存是被编址了的存储单元。

     ->变量一定是进程的变量,进程指的是执行中的程序。

  变量类型:声明变量的类型是为了事先确定好数据的存储二进制格式,和存储长度。

   ->变量类型分类:

       1,字符类型

       2,数值类型:

         (1)整型

         (2)浮点型:

            浮点数就是小数,浮点数是分开存放的,小数点之前作为一个单位存放,小数点之后作为一个单位存放,然后再存放小数点的位置。

       3,布尔型(真假型):

          也称为逻辑型->

            逻辑运算:与、或、非、异或。

            在逻辑运算中,1代表真,0代表假。

            逻辑与运算:&&

            逻辑或运算:||

            逻辑非运算:!单目运算符,只需要一个操作数

            计算机的内部是由逻辑门电路组合起来的。

            短路逻辑运算:

               对于逻辑与运算来说,只要有一个为假,那么结果一定为假(串联关系)。

               对于逻辑或运算来说,只要有一个为真,那么结果一定为真(并联关系)。

  变量赋值

    ->VAR_NAME=value

        bash脚本编程之一_Linux

  变量溢出

    ->指的是用户输入数据的长度超过了所声明变量类型的长度,导致数据溢出的现象。

    ->缓冲区溢出:由于用户输入数据的长度超过了变量类型的长度,导致数据溢出,溢出的数据恰巧控制了系统的管理进程。

    ->防止缓冲区溢出:在接收用户输入的数据之前,先在程序中判断是否会导致溢出现象发生。

    ->有解释器的语言,通常变量类型均为弱类型的,因为解释器可以解决变量溢出的问题,这是程序本身的保护机制。

    ->但凡编译型语言的变量类型均为强类型的,但是编译器在编译的时候也会帮我们检查是否存在变量溢出的问题。

·bash脚本

    变量命名规则

        ->只能包含字母、数字、下划线,并且不能以数字开头。

        ->不能和系统中已有的环境变量重名。

        ->最好做到见名知义。

    变量类型

        ->环境变量:

        作用域为当前shell进程或当前shell进程的子进程,只对当前shell有效。

        环境变量的声明:export VAR_NAME=value,export相当于是导出的意思。

            bash脚本编程之一_Linux_02

        脚本在执行的过程中会启动当前shell的一个子shell进程,命令行中启动的脚本会继承当前shell的环境变量,系统自动启动的脚本(非命令行启动)就需要自我定义各种环境变量。

        ->本地变量(局部变量是本地变量的子概念):

        本地变量的声明:

            set命令:set(set可以省略) VAR_NAME=value

                作用域为整个bash进程

                bash脚本编程之一_Linux_03

        局部变量的声明:

            local VAR_NAME=value

                作用域为当前代码段

                bash脚本编程之一_Linux_04

        ->变量引用:

            格式:${VAR_NAME}花括号可以省略,变量替换,变量引用。

                bash脚本编程之一_Linux_05

            ‘’单引号强引用,语句段内的变量不做变量替换,输出变量本身。

                bash脚本编程之一_Linux_06

            “”双引号弱引用,语句段内的变量会进行变量替换。

                bash脚本编程之一_Linux_07

        ->位置变量:

            $1,$2,$3,...用来引用脚本参数。

        ->特殊变量(系统变量):

            是bash内置的,用来保存某些特殊数据的变量。

            $? 保存上一个命令的执行状态返回值,命令正确执行返回0,命令错误执行则返回1-255中的任意数字,针对255中错误类型。

            bash脚本编程之一_Linux_08

            命令执行之后可能有两类返回值:

             1,命令的执行结果。

             2,命令的执行状态返回值(0-255)

                    返回0值,表示命令是正确执行的

                    返回1-255的值,表示返回的是各种错误,1,2,127三个号码是系统预留的,有特殊用途,其他代号可以用户自定义。

        ->输出重定向

            > 重新定向到标准输出,覆盖原有内容。

                bash脚本编程之一_Linux_09

            >> 追加输出,保留原有内容。

                bash脚本编程之一_Linux_10

            2> 重新定向错误输出。

                bash脚本编程之一_Linux_11

            2>> 追加定向错误输出。

                bash脚本编程之一_Linux_12

            &> 重定向标准输出和错误输出到同一个文本,重定向所有。

                bash脚本编程之一_Linux_13

            &>> 追加重定向所有输出

                bash脚本编程之一_Linux_14

            /dev/null: 软件设备,bit bucket(位桶),也叫做数据黑洞,一般如果不想要命令的执行结果显示到标准输出上,那么就在命令后面直接跟上重定向所有到/dev/null。

                bash脚本编程之一_Linux_15

        ->撤销变量

            格式:unset VAR_NAME->不需要加$,因为撤销的是变量而不是变量的值。

               bash脚本编程之一_Linux_16 

        ->查看当前shell中的变量

            set命令:用来查看所有变量,包括环境变量和本地变量。

               bash脚本编程之一_Linux_17 

            查看环境变量:

                printenv

                bash脚本编程之一_Linux_18

                env

                bash脚本编程之一_Linux_19

                export

                bash脚本编程之一_Linux_20

            特殊变量和位置变量无法查看

    shell默认是不能做算术运算的,默认所有变量的值都是字符串。


·脚本

    ->其实就是命令的堆砌。

    ->按照实际需要,结合命令流程控制机制实现具体功能的源程序。

            

    我们在编辑器中编写好的程序只是一些二进制ASICLL文本,而我们的linux内核却只能识别ELF(可执行的、可链接的文件格式)文件,这时候我们就得需要需要一个shebang(指定程序的魔数),也就是我们常说的解释器。

    shebang

        写法:#!后面跟上解释器脚本的路径,写在脚本中的第一行(脚本中的第一行必须这么写,其后所有加#的行全为注释行,不执行)。

    bash脚本编程之一_Linux_21

    练习:写一个脚本,要求:

        1,添加5个用户,zhubo1,zhubo2,zhubo3,zhubo4,zhubo5

        2,每个用户的密码同用户名,而且要求,添加密码完成后,不显示passwd命令的执行结果信息

        3,每个用户添加完成后,都要显示用户某某已经成功添加

        bash脚本编程之一_Linux_22

        程序执行结果:

        bash脚本编程之一_Linux_23

    练习:写一个脚本,要求:

        1,使用一个变量保存一个用户名

        2,删除此变量的用户,且一并删除其家目录

        3,显示“用户删除完成”类的信息

        bash脚本编程之一_Linux_24

        程序执行结果:

        bash脚本编程之一_Linux_25

  条件判断

    练习:写一个脚本,要求

        1,给定一个用户

        2,如果用户不存在,则添加该用户,给密码并显示已添加成功

        3,如果用户存在,则显示用户已存在

    bash脚本编程之一_Linux_26

    脚本执行结果:

    bash脚本编程之一_Linux_27

    练习:写一个脚本,要求

        1,给定一个用户

        2,如果用户存在,则显示该用户已存在

        3,如果该用户不存在,则添加该用户,并给密码并显示已添加成功

    

    bash脚本编程之一_Linux_28

    脚本执行结果:

    bash脚本编程之一_Linux_29


  bash中如何实现条件判断:

     条件测试类型:

      1,整数测试:

         整数比较(双目操作):需要两个操作数

            ->-eq(equal):测试两个整数是否相等,比如$A -eq $B,测试AB中的值是否一样,如果一样则状态返回值为0,等值比较。

            ->-ne(not equal):测试两个整数是否不等,不等为真,等值为假。

            ->-gt(greater than):测试一个数是否大于另一个数,大于为真,否则为假。

            ->-lt(less than):测试一个数是否小于另一个数,小于为真,否则为假。

            ->-ge(greater equal):大于或等于。

            ->-le(less equal):小于或等于。

      2,字符测试

      3,文件测试:判断文件是否存在

     条件测试的表达式:

      1,[ expression ]

      2,` expression `bash的关键字

      3,test命令+expression

        

    bash中命令间的逻辑关系:

        逻辑与:&&

        第一个条件为假时,第二个条件不用再判断,最终结果已经有了。

        第一个条件为真时,第二个条件必须得判断。

        逻辑或:||

    ! id xxx && useradd xxx &&之前为真时,才会执行&&之后的内容,否则&&之后的内容不会执行。

    id xxx || useradd xxx ||之前为假时,才会执行||之后的内容,否则||之后的内容不会执行。


    练习:写一个脚本,要求

    1,添加三个用户,但要先判断用户是否存在,不存在才能添加。

    2,最后显示当前系统上共有多少个用户。

    bash脚本编程之一_Linux_30

    脚本的执行结果:

    bash脚本编程之一_Linux_31

    练习:写一个脚本,要求

        给定一个用户:

        1,如果其UID为0,就显示此用户为管理员。

        2,否则,就显示其为普通用户。

    bash脚本编程之一_Linux_32

    脚本执行结果:

    bash脚本编程之一_Linux_33

    

    条件判断->控制结构:

    ->单分支的if语句(if...then写一行时,then之前要加分号,不写到一行的时候则不用加分号):

        格式:if 判断条件

              then

                expression1

                expression2

                ...

               fi

    ->双分支的if语句

        格式:if 判断条件

              then

                expression1

                expression2

                ...

              else

                expression1

                expression2

                ...

               fi


    id xxx 是用来判断用户xxx是否存在的命令

        if [ `id -u xxx` -eq 0 ]->利用的是命令的执行结果值0或者1。

        if id xxx->利用的是命令的执行状态返回值。



    练习:

    判断当前系统上是否有用户的的默认shell为bash

    如果有,就显示有多少个这类用户;

    否则,就显示没有这类用户。

    bash脚本编程之一_Linux_34

    脚本执行结果:

    bash脚本编程之一_Linux_35

    ->引用命令的执行结果必须使用反单引号

    

    练习:

    判断当前系统上是否有用户的默认shell为bash

    如果有,就显示其中一个的用户名

    否则,就显示没有这类用户

    bash脚本编程之一_Linux_36

    脚本执行结果为:

    bash脚本编程之一_Linux_37

    练习:

        给定一个用户,判断其UID和GID是否一样

        如果一样,就显示此用户为"good guy";否则,就显示此用户为"bad guy"。

    bash脚本编程之一_Linux_38

    脚本执行结果为:

    bash脚本编程之一_Linux_39

    如果不使用id命令,该如何获得id号:

    bash脚本编程之一_Linux_40

    脚本执行结果为:

    bash脚本编程之一_Linux_41

    

 shell中如何进行算术运算

    A=3

    B=6

    1,let 算术运算表达式->let C=$A+$B

    2,$[算术运算表达式]->$[C=$A+$B]

    3,$((算术运算表达式))->$((C=$A+$B))

    4,expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用

        ->expr C = $A + $B


    练习:

    判断命令历史中,历史命令的总条目是否大于1000

    如果大于,则显示"some command will gone."

    否则,显示"OK."

    bash脚本编程之一_Linux_42

    脚本执行结果:

    bash脚本编程之一_Linux_43