Shell脚本编程基础之一

  Linux为高效管理系统,提供了CLI命令行接口,供用户在命令提示符下输入命令,它有很多bash shell基础特,根据这些特性能够很灵活的使用命令,也支持使同时输入多个命令执行,命令之间用冒号分隔;但是要完成复杂多次重复性的操作,非常不便,系统管理工作变得很是繁忙,很难轻松完成工作任务;不过Linux的shell支持脚本编程,通过编写纯文本格式的脚本,执行起来很是满足自动化要求;不过要想使用它,必须合理规范编写它,现在Linux系统默认的shell类型基本都是bash shell,所以学习bash shell脚本编程很是实用;

*章节


1)编程基础

2)脚本基本格式

3)变量


4)逻辑运算

5)算术运算

6)条件测试


1.编程基础:

  编程语言风格:

      我们知道程序是由指令加数据两部分组成,cpu通过指令对数据加以处理,要想编写程序,必须有一定的编程风格,可以分为两大类;(1)过程式:编写以指令为中心,注重指令检查规范,数据服务于指令;(2)对象式:编写以数据为中心,注重对象的定义,指令服务于数据;

    编程语言类型:

     运行在计算机最底层的是二进制程序指令,也就是0和1,编写庞大的0和1对于人来说太困难了,于是有了汇编语言,这种语言是跟硬件紧密结合的,需要非常熟悉了解硬件的特性,才能够编写出来,所有这种汇编语言还是比较低级,于是有了高级语言,这种语言对人来说还是相对比较容易理解编写,最终执行还是需要转换,高级语言也有不同类型,像JAVA,C++这种属于编译型高级语言,需要编译器转换成目标代码,而shell,Perl,Python是属于解释型语言,需要解释器转换成机器代码。

2.脚本的基本格式:

      

$cat test1.sh
#!/bin/bash
#
#author:root
#version:1.1
#description:the first script ;



echo "hell user ,how are you ?"

$bash -x test1.sh
hell user ,how are you ?

   脚本要求:

   (1)必须指明脚本的shebang;也就是脚本的第一行,必须顶格写#!/bin/bash,指明执行脚本要用的shell类型,这里的#不是注释,要注意;

   (2)要有基本的脚本说明信息,这样利于脚本的管理使用,一般有日期,作者是谁,描述,版本等, 注意:#开头的行,bash shell默认不执行;

   (3)复杂的代码片段要写代码注释信息;方便自己和他人后期使用;

   (4)脚本中要有适当的缩进和空白行,这样脚本内容看起来层次分明,结构清晰;

   (5)在脚本中使用定义变量,需要根据实际遵循一定的命名规范;后面变量详细说明;

    

   执行脚本的方式:

   (1)把脚本当做参数,给bash直接当做参数执行;

   (2)chmod +x script 授予脚本执行权限x,使用绝对路径或相对路径来执行脚本;

  

   脚本调试检查:

    (1)尤其是复杂大的脚本尤其要事先检查脚本语法格式,避免任务执行一半的故障;解决很是麻烦;

$ bash -n  /path/to/script       ///检查语法命令格式

$ bash -x /path/to/script        ///调试脚本 :可以看到脚本的执行过程,初期学习,对于复杂场景分析很是实用

    

  定义脚本退出状态码

     exit: 退出脚本

     exit #

        如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码;

3.变量

   :变量是命名的内存空间,是一个可变化的量,定义好之后,可以在脚本中多次引用变量值,对于后期的修改和调整很是方便;

   (1)变量类型:

      定义了变量类型,也就决定了数据的存储格式,变量数据范围,变量能够参与的运算;这里的bash shell 可分类为:

      a)字符型;

      b)数值型:数值由包括整数型和浮点型;

   

   (2)注意:对于强类型语言比较说java python这些大型编程语言,对于变量的使用必须要事先声明类型,否则语法错误,而对于bash shell 这种只支持脚本的弱类型编程语言,变量在使用不需要声明,默认变量类型为字符型,默认当做字符处理;

  

   (3)变量的命令规则:

      a)首先不能使用系统定义过和系统保留字,比如说一些测试表达式的关键字,if,如果使用了系统变量,脚本执行是会覆盖系统变量值,造成其他执行环境错乱;

      b)只能使用字母数字下划线,不能以数字开头;

      c)变量能够做到见名知意;

      d)命名使用一定要有语言规范,比如说驼峰命名法,具体根据实际生产环境使用场合调整;

      

   (4)根据变量的作用生效范围分类:

      a)局部变量:只对当前的shell脚本代码段有效;

      b)本地变量:只对当前shell进程生效,不包含子进程;

      c)环境变量:对当前shell进程及其子进程都生效;

      d)位置参数变量:

         $1:引用的是脚本后跟的第一个参数,$2:引用的是脚本后跟的第二个参数;…${10}:表示引用的是脚本后跟的第十个参数…(注意:这里大于9以上要用花括号“{ }”);

     e)特殊变量:

         $?:判断上一条命名的执行状态结果;

         $0:引用的是脚本的本身完成的路径名;

         $#:表示的参数个数;

         $*:表示的是参数的集合,不过这里表示的是把所有的参数当成一个字符串整体;

         $@:表示的是所有的参数,不过这里表示的是把每个参数当成一个个独立的参数字符串; 

      

      程序执行结果

      程序执行,可能有两类返回值:程序状态返回代码(0-255)


         0: 正确执行

     1-255:错误执行,1,2,127系统预留

         

    (5)变量赋值:

          1.本地变量赋值:

           set VARNAME=VALUE

            注意:set可以省略不写

          2.环境变量赋值:

            export VARNAME=VALUE

            注意;也可以先赋值后设置成环境变量,方法如下

            VARNAME=VALUE

            export VARNAME

          3.局部变量赋值:

               local VARNAME=VALUE

               注意可以不写local,因为在脚本中会定义的变量,作用在局部;

          4.追加赋值:

              VARNAME=$VARNAME:VALUE

               注意:追加变量赋值,要用冒号;

         

     

     (6)查看变量:

             查看shell中所有变量:

$set

             查看当前shell中的环境变量:

$printenv
 
$env

$export

      (7)撤销变量:

$unset VARNAME       ///注意这里指定变量名即可撤销;

       

      (8)变量引用:

$ var1=tom
$ echo "hello $var1"
hello tom

         注意:在引用变量时,如果后面跟其他字符,注意用花括号“{ }”引起来,避免混乱;如下

$ var1=Tom 
$ ehco "$var1and I  like to read books."
I like to read books.                        ///这里表示引用的:是一个叫var1and的变量名,var1and 没有赋值;

$ var1=Tom
$ ehco "${var1}and I  like to read books."
Tomand I like to read books.

        注意:"" 两个双引号表示弱引用,变量名会替换变量值; ''两个单引号表示的是强引用,引用是不替换变量值,

$ var2=xiaoming
$ echo "hello $var2"
$ hello xiaoming
$
$ ehco 'hello $var2'
$ hello $var2

      (9)“两个反引号可以实现命令替换引用

$ whoami 
xia
$ var3=`whoami`
$ echo "how are you $var3"
how are you xia

      (10)只读变量:只读变量设定后不能再次赋值,生效范围只在当前shell进程,不包含子进程。

         设置方式:

              a) readonly VARNAME=VALUE

              b) declare -r VARNAME=VALUE

$ readonly  xsx=xiashixiang
$ echo $xsx
xiashixiang
$ xsx=hello
-bash: xsx: readonly variable      ///这里直接报错,说只读变量不可再次赋值;
$ unset xsx
-bash: unset: xsx: cannot unset: readonly variable    ///这里也说明只读变量不可撤销,只能重新登录当前shell

4.逻辑运算:

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

1: 真

0: 假

1 & 0 = 0

0 & 1 = 0

0 & 0 = 0

1 & 1 = 1

总结:做与运算两者为真,结果才为真;

或:

1 & 0 = 1

1 & 1 = 1 

0 & 1 = 1

0 & 0 = 0 

总结:做或运算只要有一者为真,结果就为真;

非:

! 真 = 假

! 假 = 真

总结:做非判断,取反;

异或

1 & 0 = 1

1 & 1 = 0

0 & 1 = 1

0 & 0 = 0 

总结:两者不同则为真,相同则为假;

命令的间逻辑关系:

    逻辑与: &&

          1.第一条命令为真时:

                  第二条命令为真时,才会执行;

                  第二条命令为假时,不会执行;

          2.第-条命令为假时:

                   第二条命令为真时,不会看

                   第二条命令为假时,不会看

                  

    逻辑或: ||

          1.第一条命令为真时:

                    第二条命令为真时,不会看

                    第二条命令为假时,不会看

          2.第一条命令为假时:

                     第二条为真时,执行第二条;

                     第二条为假,不会执行;

                    

5.算术运算:

bash默认对字符处理 

1.基本运算符:

  + – * / ** %

  注意)*:乘法符号有时在特定情境下需要转义”/*“;

2.运算方式:遵循算术运算格式

  (1)let var=算术运算表达式

  (2)$[算术运算表达式]

  (3)$((算术运算表达式))

  (4)expr 算术运算表达式(注意算术符之间必须有空格分割)

      引用var=$(expr $ARG1 $OP $ARG2)

  (5)echo "options;expression"|bc

  (6)下面一一列举算术运算表达式:

$ a=100
$ b=3
$ let var3=$a+$b
$ echo $var3
103
$
$ echo $[$a+$b]
103
$
$ echo $[a+b]
103
$
$ echo $(($a+$b)) 
103
$
$ expr $a + $b
103
$
$ expr $a * $b
expr: syntax error           ///注意这里的乘法符号没有转义语法报错;
$
$ expr $a \* $b
300
$
$ var4=$(expr $a + $b)
$ echo $var4
103

6.条件测试:

   根据数据类型测试可以分为如下:

   (1)整数测试;

   (2)字符测试;

   (3)文件测试:

   

   条件测试的表达式:

  [ expression ]

  [[ expression ]]

  test expresion

  *注意:方括号中的表达式两边必须有空格,否则语法错误如下;

#[100 -eq 100 ]
-bash: [100: command not found

 

1.整数测试操作符:要做整数测试,需要用到整数比较符号;

   -eq :测试两个整数是否相等;相等测为真,不等则为假;

#a=100
#b=100
#[ $a -eq $b ]
#echo $?
0
#
#b=200
#[ $a -eq $b ]
#echo $?
1

   -ne:测试两个整数是否不等,不等为真,相等为假;

#a=100
#b=200
#[ $a -ne $b ]
#echo $?
0
#
#b=100
#[ $a -ne $b ]
#echo $?
1

    -gt:测试一个前一个整数是否大于后一个整数,大于为真,不大于为假;

#a=200
#b=100
#[ $a -gt $b ]
#echo $?
0
#
#a=10
#[ $a -gt $b ]
#echo $?
1

    -lt:测试前一个整数是否小于后一个整数,小于为真,不小于为假;

#a=100
#b=200
#[ $a -lt $b ]
#echo $?
0
#
#a=300
#[ $a -lt $b ]
#echo $?
1

    -ge:测试前一个整数是否大于或等于后一个整数,大于或等于则为真,不大于或等于则为假;

#a=100
#b=10
#[ $a -ge $b ]
echo $?
0
#b=100
#[ $a -ge $b ]
#echo $?
0
#b=200
#[ $a -ge $b ]
#echo $?
1

    -le:测试前一个整数是否小于或等于后一个整数,小于或等于则为真,不小于或等于则为假;

#a=100
#b=200
#[ $a -le $b ]
#echo $?
0
#a=200
#[ $a -le $b ]
#echo $?
0
#a=300
#[ $a -le $b ]
#echo $?
1

2.字符测试操作比较符;

    *注意:

        (1)字符或字符串比较,需要用两个方括号“[[ ]]”,否则就无法判断;

        (2)字符比较严格区分大小写,默认根据字母逆序排大小,b大于a;同时大写字母大于小写字母,B大于b;相同则向下逐级比较;

        

    == 测试两个字符或字符窜是否相同,相同为真,不同为假;

#var5=xiaoming
#var6=xiaoming
#[[ $var5 == $var6 ]]
#echo $?
0
#var6=xiaohong
#[[ $var5 == $var6 ]]
#echo $?
1

   != 测试两个字符或字符串是否不同,不同为真,相同为假;

#var5=aaa
#var6=bbb
#[[ $var5 != $var6 ]]
#echo $?
0
#var6=aaa
#[[ $var5 != $var6 ]]
echo $?
1

   > 测试前一个字符或字符串是否大于后一个字符或字符串,大于则为真,不大于则为假;

   < 测试前一个字符或字符串是否小于后一个字符或字符串,小于则为真,不小于则为假;

#var7=AAA
#var8=aaa
#[[ $var7 > $var8 ]]
# echo $?
0
#
#[[ $var7 < $var8 ]]
#echo $?
1

   

   -n string: 测试指定字符串是否不为空,不空则真,空则假;

   -z string: 测试指定字符串是否为空,不空为真,不空则为假;

#var9=xia
#[[ -n $var9 ]]
#echo $?
0
#[[ -z $var9 ]]
#echo $?
1
#var9=
#[[ -z $var9 ]]
#echo $?
0

3.文件测试:

   (1)文件存在测试:

    -e FILE:测试文件是否存在,存在则为真,不存在则为假;

    -a FILE:等同于-e

   (2)文件类别测试:

    -d FILE:测试是否为目录,目录为真,不是目录为假;

    -f FILE:测试是否为普通文件,是普通文件则为真,不是则为假;

    -p FILE:测试是否为命名管道文件,是为真,不是为假;

    -h FILE:测试是否为软连接文件,是软连接文件则为真,不是则为假;

    -L FILE:等同于-h

    -S FILE:测试是否为套接字文件,是套接字文件则为真,不是则为假;

    -b FILE:测试是否为块设备文件,是块设备文件则为真,不是则为假;

    -c FILE:测试是否为字符设备文件,是字符设备文件则为真,不是则为假;

   (3)空文件测试

    -s FILE:测试是否为空文件,也就是文件大小为0,文件存在且为空则为真,文件有数据则为假;

   (4)文件权限测试

    -r FILE:测试当前用户是否对文件有读权限,有则为真,没有则为假;

    -w FILE:测试当前用户是否对文件有写权限,有则为真,没有则为假;

    -x FILE:测试当前用户是否对文件有执行权限,有则为真,没有则为假;

    

    (5)文件特权权限测试:

    -u FILE:测试文件是否有suid权限,有则为真,没有则为假;

    -g FILE:测试文件是否有sgid权限,有则为真,没有则为假;

    -k FILE:测试文件是否有sticky权限,有则为真,没有则为假;

    

    (6)文件属主属组测试:

    -O FILE:测试当前用户是否是文件的属主,是为真,不是则为假;

    -G FILE:测试当前用户是否是文件的属组,是为真,不是则为假;

    

   (7)文件双目测试:

    FILE1 -ef FILE2 :测试两个文件的的inode是否相同,也就是说是两个相同的硬链接文件;

    FILE1 -nt FILE2 :测试FILE1是否新于FILE2,也就是说FILE2是老文件,FILE1新为真,FILE2新为假;

    FILE1 -ot FILE2 :测试FILE1是否旧于FILE2,FILE1新为假,旧为真;

  

  

原创文章,作者:xiashixiang,如若转载,请注明出处:http://www.178linux.com/34717

(0)
xiashixiangxiashixiang
上一篇 2016-08-15
下一篇 2016-08-15

相关推荐

  • 第四周

    第四周blog 第四周blog 1 复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。 cp -r /etc/skel /home/tuser1 ; chmod -R go-r /home/tuser…

    Linux干货 2016-12-23
  • Linux简单命令

    cal 日历 bc  计算器     obase=2 输出为二进制       ibase=2输入为二进制      \onnn八进制      \xHH十六进制 $()识别命令和变量,同反向单引号 , 可在命令调用另一个命令的执行结果时用 字体颜色:红色-打包文件(压缩包),绿色-可执行,浅蓝-软连接,蓝色-目录 echo $SHELL查看当前shell …

    Linux干货 2018-03-18
  • 分布式系统的事务处理

    当我们在生产线上用一台服务器来提供数据服务的时候,我会遇到如下的两个问题: 1)一台服务器的性能不足以提供足够的能力服务于所有的网络请求。 2)我们总是害怕我们的这台服务器停机,造成服务不可用或是数据丢失。 于是我们不得不对我们的服务器进行扩展,加入更多的机器来分担性能上的问题,以及来解决单点故障问题。 通常,我们会通过两种手段来扩展我们的数据服务: 1)数…

    Linux干货 2016-08-15
  • Shell脚本编程 流程控制—选择

    流程控制可根据不同的情况做不同的处理,而且可重复执行指定的程序区域,在shell bash中流程控制可分为两大类: "选择"和"循环" 1.选择:if、case、select 2.循环:for、while、until、select 命令结束状态返回值: 在shell中命令执行状态返回值分两种,成功和失败,0表示成功,非…

    Linux干货 2016-08-24
  • n28-第四周

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限 答:install 复制文件并设置属性 -d, –directory:复制所有参数为目录名 -m, –mode=MODE:设置文件属性,相当于chmod # install -d -m u=rwx /e…

    Linux干货 2017-12-24
  • M20 – 1- 第二周(2):硬链接与软链接的区别

    在讲硬链接与软链接的区别之前,我们首先了解inode,了解inode让我们更容易理解何为硬链接和软链接。 inode概念        何为inode,inode就是索引节点,而inode表中存放着文件的元数据,何为元数据,元数据就是文件名称、大小、时间戳、所有者、权限、inode等信息,而文件中的内容就是文件的数据,…

    Linux干货 2016-08-02

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-15 17:06

    总结的很详细,作业需要不上来哦。