Shell脚本编程

shell脚本编程

Bash为用户提供了编程环境

相对于计算机而言,只能识别二进制文件,因此其所运行的其实是二进制指令,而这些二进制指令我们称之为机器语言,属于低级语言;程序员编程所使用的语言为高级语言,是人们比较容易理解的语言;因此,程序的执行过程:先把源码程序翻译成机器语言(生成可执行的文件),然后解释执行。
程序( 程序=指令+数据 )的编程风格有两种:

  • 面向过程的编程:以指令为中心,数据服务指令
    面向对象的编程:以数据为中心,指令服务数据;

shell程序是一个过程式的解释器,提供了编程能力,然后解释执行;对于过程式编程而言,把一行源码程序翻译成机器语言,然后执行,再翻译下一行的源码程序为机器语言,然后执行;

  • 编译过程:高级语言–>编译器–>目标代码 
    需要提前编译,编译成机器可以理解二进制文件,然后再执行
    靠近底层,执行效率非常高,跨平台性比较差
    C++ CentOS—-> SuSE(腾讯云)
    C#(微软) 只能在windows运行 
    IIS C# .net SQLServer
    Golang
  • 解释过程:高级语言–>解释器–>机器代码
    并不需要提前编译,只需要把代码转换成中间代码,边解释边运行
    执行效率稍逊,跨平台
    JAVA、 Python 、Shell 、PHP 、Ruby

shell脚本:

shell脚本其实就是一系列命令组合起来的文本文件,利用这些命令组合起来完成一个或者一项功能;

  • shell脚本开头环境的指定:

    #!/bin/bash
    #
    #Filename:BeiFen.sh
    #Description:Test
    #Author:Li Nan
    #Email:xxx@126.com
    #Revision:3.1
    #Date:20170407
    #Note:Test

    # 表示注释,此行不执行

  • shell脚本组成:
    变量
    命令
    控制语句(if、for、while)

  • 运行脚本:
    1、给予执行权限,通过具体的文件路径对指定文件执行;

    • 加执行权限
      1)相对路径
      2)绝对路径
      3)放到$PATH变量指定的目录里面,直接执行(tab)

    2、直接运行解释器,将脚本作为解释器程序的参数运行;

    • bash、sh

    3、脚本调试执行:

    • bash -n 检查语法错误,不检查拼写错误
      bash -x 显示脚本执行的时候每一个命令具体的执行结果

变量

  • 变量:命名的内存空间
  • 数据存储的方式:字符、数值;
  • 变量的作用:

    • 1、数据存储格式
      2、参与的运算
      3、表示的数据范围

变量的类型:

  • 字符
    数值:整型、浮点型
    注:相同类型的数据在一起才可以进行运算,数值型和字符型不能运算

  • 对于编程语言来说还分为:强类型、弱类型;

    • 强类型:JAVA C# 
      数值型和字符型不能直接计算
      除非显式 把字符型转换成数值型才可以计算

      C++ 
      int a=10;
      char a=10
      double b=10

    • 弱类型 :shell php
      不会严格区分变量类型
      定义变量的时候不用指定变量类型,默认字符型
      如果想要计算的时候,会自动帮你转换成数值型

      Shell
      I=10
      J=2

变量的命名规则:

  1. 不能使用if for bash cd ls date关键字
  2. 不能以数字开头,不能使用特殊符号
    只能使用数字 字母及下划线
  3. 见名知义
  4. 建议变量使用大写

bash变量的种类

  • 本地变量(全局变量): 仅仅对当前shell生效

    • 变量的赋值:name=’value’
      value 可以使用引用:

      1、可以直接使用字符串;name = “username”
      2、变量引用:name = “$username”
      3、命令引用:name=COMMAND,name=$(COMMAND)

    • 变量引用:$name、${name}
      “” :弱引用 会把双引号里面的变量替换
       ”  :强引用 不会把引号里面的变量进行替换
      “ : 把反引号里面的命令执行结果赋值给变量
      HZ=$SH 用变量赋值变量

    • 显示已定义的所有变量:set

    • 取消变量:unset name

      • 取消变量和变量置空是两种不同概念
        unset HZ
        HZ=
  • 环境变量 : 对当前shell以及其他shell都生效,使用export可使变量改变为环境变量
    子shell只会继承环境变量,并不会继承父shell中的变量

    • 变量声明、赋值:

      1. export name = VALUE
      2. name = VALUE
        export name
      3. declare -x name = VALUE
      4. name = VALUE
        declare -x name
    • 变量引用:$name、${name}

    • 显示所有环境变量:export、env、printenv、declare -x 、set
    • 取消变量:unset name

Bash中有很多内建的环境变量(大写):PATH,SHELL,UID,HISTSIZE,PWD,OLD,HISTFILE,PS1等。

  • 局部变量(私有变量) :通常用在函数里面,使用local定义
  • 位置变量:$1,$2,…$n,${10}来表示,用于放在脚本代码中调用通过命令行传递给它的参数;
    shift + [n] 换位置
  • 特殊变量: 
    $?:上个命令执行成功与否的结果
    $0:表示命令本身
    $#:传递给脚本参数的个数
    $*:传递给脚本的所有参数,(全部参数合为一个字符串)
    $@:引用传递给脚本的所有参数,(每个参数为独立字符串)
    当被括号括起来的时候会看出区别
    $$:显示此脚本的进程号

  • 只读变量:
    只能声明,但不能修改和删除
    声明只读变量:
    readonly name
    declare -r name
    查看只读变量:
    readonly -p

变量的高级操作

  • 字符串切片

    • ${变量:位置起点}
      由指定的位置开始,截取字符串到字符串结束
    • ${变量:位置起点:长度}
      eg:MYNAME=”123456789″
      substr2=${MYNAME:4:6}
    • 计算字符串长度
      ${#变量名称}
      传回变量值的字符串长度
      filename=”/usr/sbin/ntpd”
      ehco ${#filename}

      PS:另一种方法:
      expr length “$filename”

    • 由前面(最左边)开始,对比变量值,删除“最短相符合的字符串”
      ${变量#样式}
      filename=”/usr/sbin/ntpdate”
      echo ${filename#/*/}

    • 由前面对比,删除最长的
      ${变量##样式}
      filename=”/usr/sbin/ntpdate”
      echo ${filename##//}


      • 由后面对比,删除最短的

        ${变量%样式}

        filename=”/usr/sbin/ntpd”

        echo ${filename%/}

      • 由后面对比,删除最长的

        ${变量%%样式}

        domainname=”www.178linux.com”

        echo ${domainname%%.*}

    • 只替换第一个对比符合的字符串
      ${变量/样式/替换字符串}
      name=”liangchenye”
      echo ${name/liang/wang}
    • 替换全部对比符合的字符串
      ${变量//样式/替换字符串}
      name=”zhaoritian”
      echo ${name//zhao/ye}
    • 把对比符合的字符串删除
      只删除一个
      ${变量/样式/}
      name=”liangchenye”
      echo ${name/liang/}
    • 把对比符合的字符串全部删除
      ${变量//样式/}
      name=”zhaoritian”
      echo ${name//zhao/}
  • 测试存在性及空值

    • ${待测变量-默认值}
      若变量不存在,则符合判断,传回默认值
      unset myname
      echo ${myaname-“fuerkang”}
    • ${待测变量:=默认值}
      若变量不存在或其值为空,则符合判断,传回默认值
      unset myname
      echo ${myname:=”fuerkang”}
    • 测试变量是否为空或者不存在,提示错误信息
      ${待测变量:?提示信息}
      echo ${name:?”sorry no name”}
    • 测试变量的存在性,若存在且非空,则符合判断
      ${待测变量:+”ture”}
      echo ${magedu:+”true”}

算数运算

bash会对数字执行隐式的类型转换

  • 运算操作符:+、-、、/、%(取余)、*(乘方)
    bash运算的实现方式:

    • (1) let num=算术表达式 ,let r=9+9
      (2) var=$[算术表达式] , r=$[9+9]
      (3) var=$((算术表达式)) , r=$((9+9))
      (4) 外部命令:expr 8 + 3 (+ 两边要有空格)
      (5)declare -i,declare -i r=9+9
      (6)bc ,echo {1..100} | tr ” ” “+” | bc

    注意 :expr 8 * 8 ;乘号需要转义

    • (7)echo $((12+$i))是否可以执行
      建议把$i中的$去掉
      正确姿势 echo $((12+i))
    • bash内建的随机数生成器,$RANDOM (0-32767)
      echo $[$RANDOM%50]:0-49之间的随机数
  • 赋值

    • 增强型赋值:
      +=, i+=3等于i=i+3 
      -=, i-=3等于i=i-3
      =, i=3等于i=i*3
      /=, 
      %=
    • 自增、自减:
      ++ 先执行 执行完加1 (用的比较多)
      ++i 先加1,再执行
      var=$[$var+1]–>let var+=1 –> let var++

    [root@Centos7 script]# a=10
    [root@Centos7 script]# b=10
    [root@Centos7 script]# let c=a++
    [root@Centos7 script]# echo $c
    10
    [root@Centos7 script]# echo $a
    11
    [root@Centos7 script]# let d=++b
    [root@Centos7 script]# echo $d
    11
    [root@Centos7 script]# echo $b
    11

字体颜色

  • 字体颜色:30——37
    echo -e “\033[30m 黑色字 \033[0m” 
    echo -e “\033[31m 红色字 \033[0m” 
    echo -e “\033[32m 绿色字 \033[0m” 
    echo -e “\033[33m 黄色字 \033[0m” 
    echo -e “\033[34m 蓝色字 \033[0m” 
    echo -e “\033[35m 紫色字 \033[0m” 
    echo -e “\033[36m 天蓝字 \033[0m” 
    echo -e “\033[37m 白色字 \033[0m”

  • 字体背景颜色40—–47
    echo -e “\033[40;37m 黑底白字 \033[0m” 
    echo -e “\033[41;37m 红底白字 \033[0m” 
    echo -e “\033[42;37m 绿底白字 \033[0m” 
    echo -e “\033[43;37m 黄底白字 \033[0m” 
    echo -e “\033[44;37m 蓝底白字 \033[0m” 
    echo -e “\033[45;37m 紫底白字 \033[0m” 
    echo -e “\033[46;37m 天蓝底白字 \033[0m” 
    echo -e “\033[47;30m 白底黑字 \033[0m”

逻辑运算

true (1)、false (0)
命令执行成功 我们认为是真 
命令执行失败 我们认为是假

  • 与运算:&&
    1 && 1 = 1
    1 && 0 = 0
    0 && 1 = 0
    0 && 0 = 0
    与的时候 只要有一个为假 那么整个结果就是假的。

  • 或运算:||
    1 || 1 = 1
    1 || 0 = 1 
    0 || 1 = 1
    0 || 0 = 0
    或的时候 只要有一个为真 那么整个结果就是真。

  • 非运算:!
    !1 = 0
    !0 = 1

  • 异或运算:
    两个数字相同为0;
    两个数字不相同为1;

短路预算:

命令1 && 命令2 命令1 成功执行 则执行命令2
命令1 执行失败 则不会执行命令2

命令1 || 命令2 命令1成功执行,则命令2不执行
命令1执行失败,则命令2执行

命令1 && 命令2 || 命令3
如果命令1 成功执行 则执行命令2 且命令3不会执行
如果命令1 执行失败 那么命令2就不会执行,则命令3执行

如果 命令1 成功
则 命令2;
否则 命令3;

退出状态

进程使用退出状态来报告成功或失败

  • 0 代表成功,1-255代表失败
    $? 变量保存最近的命令退出状态

[root@magedu bin]# ping -c1 -W1 hostdown &> /dev/null
[root@magedu bin]# echo $?
2

  • exit [n]:自定义退出状态码
    注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
    注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

测试条件

  • test 测试条件
    [ 测试条件 ]
    [[ 测试条件 ]] 条件测试的前后要加上空格
    生产环境建议使用两个中括号

  • 数值测试:
    -gt: 是否大于
    -ge: 是否大于等于
    -eq: 是否等于
    -ne: 是否不等于
    -lt: 是否小于
    -le: 是否小于等于

    [root@Centos7 script]# [ 1 -gt 2 ] && echo “OK”
    [root@Centos7 script]# [ 3 -gt 2 ] && echo “OK”
    OK
    [root@Centos7 script]# 
    [root@Centos7 script]# [ 3 -ge 2 ] && echo “OK”
    OK
    [root@Centos7 script]# [ 2 -ge 2 ] && echo “OK”
    OK

  • 字符串测试:

    == 是否等于
        [[ "abs" == ??? ]] 使用通配符不加引号
        > 是否大于
        < 是否小于
        != 是否不等于
        =~ 左边的字符串是否包含右边指定的字符串
        -z 测试字符串是否为空
        -n 测试字符串是否不为空
        -f filename

    注:此表达式一般用于[[]]中,并且用于字符串比较时用到的操作数都应该使用引号;

    [[ -f filename ]] 应用:
    [root@Centos7 script]# [[ -f /etc/profile ]] && echo “OK” || echo “not OK”
    OK
    [root@Centos7 script]# 
    [root@Centos7 script]# [[ -f /etc/profilefdfd ]] && echo “OK” || echo “not OK”
    not OK
    [root@Centos7 script]# 
    [root@Centos7 script]# [[ -f /etc/ ]] && echo “OK” || echo “not OK”
    not OK

  • 文件测试

    • 文件存在性测试:
      -e FILE:文件存在性测试,存在为真,否则为假
      -a FILE:同-e
    • 存在性及类别测试
      -b FILE:是否存在且为块设备文件
      -c FILE:是否存在且为字符设备文件
      -d FILE:是否存在且为目录文件
      -f FILE:是否存在且为普通文件
      -h FILE 或 -L FILE:是否存在且为符号链接文件
      -p FILE:是否存在且为命名管道文件
      -S FILE:是否存在且为套接字文件

    • 文件权限测试:(针对于当前用户)
      -r FILE:是否存在且可读
      -w FILE:是否存在且可写
      -x FILE:是否存在且可执行

    • 文件特殊权限测试:
      -u FILE:是否存在且拥有suid权限
      -g FILE:是否存在且拥有sgid权限
      -k FILE:是否存在且拥有sticky权限

    • 文件大小测试:
      -s FILE:是否存在且非空

    • 文件是否打开:
      -t fd:fd表示文件描述符是否已经打开且与某终端相关
      -N FILE:文件自从上一次被读取之后是否被修改过
      -O FILE:当前有效用户是否为文件属主
      -G FILE:当前有效用户是否为文件属组

组合测试条件

  • COMMAND1 && COMMAND2 并且
    COMMAND1 || COMMAND2 或者
    ! COMMAND 非
    如:[[ -r FILE ]] && [[ -w FILE ]]

  • EXPRESSION1 -a EXPRESSION2 并且
    EXPRESSION1 -o EXPRESSION2 或者
    ! EXPRESSION 
    “!” 最高,”-a” 次之,”-o” 最低。

[]与[[]]的区别

  • [ $A == “boy” ]
    报错:-bash:[: ==:期待一元表达式
    使用[ “$A” == “boy” ]
    或者[ X”$A” == X”boy” ] 或者 [[ “$A” == “boy” ]] ( 最佳方案)

  • [ 1 > 2 ]
    使用 [[ 1 > 2 ]]不用对大于号进行转义

  • [[ ]]支持通配符和正则表达式
    [[ “aaa” == ??? ]]
    [[ “aaa” =~ .{3} ]] 扩展正则表达式

bash的配置文件

  • 按生效范围划分,存在两类:

    • 全局配置:
      /etc/profile
      /etc/profile.d/*.sh
      /etc/bashrc
    • 个人配置:
      ~/.bash_profile
      ~/.bashrc
  • 按功能划分,存在两类:

    • profile类:为交互式登录的shell提供配置

      • 全局:/etc/profile,/etc/profile.d/*.sh
      • 个人:~/.bash_profile

        功用:

      • 用于定义环境变量
      • 运行命令或脚本
    • bashrc类:为非交互式和交互式登录的shell提供配置

      • 全局:/etc/bashrc
      • 个人: ~/.bashrc

        功用:

      • 定义命令别名和函数
      • 定义本地变量
  • shell登录两种方式

    • 交互式登录:

      • 直接通过终端输入账号密码登录;
      • 使用 “su – UserName” 切换的用户

        执行顺序:

        /etc/profile –> /etc/profile.d/*.sh –> ~/.bash_profile –> ~/.bashrc

        –> /etc/bashrc

    • 非交互式登录:

      • su UserName
      • 图形界面下打开的终端
      • 执行脚本

        执行顺序:

        ~/.bashrc –> /etc/bashrc –> /etc/profile.d/*.sh

  • 编辑配置文件生效

    • 重新启动shell进程
    • . 或 source

bash 退出任务

  • 保存在~/.bash_logout文件中(用户)
  • 在退出登录shell时运行
  • 用于:创建自动备份;清除临时文件;

语句控制

  • 过程式编程语言有三种过程:
    顺序执行:按照顺序一条一条语句执行
    选择执行:按照条件进行选择执行
    循环执行:按照给定的循环条件进行循环执行
    其中顺序执行不需要特定的控制,只需要按照语句依次执行即可;选择执行,则需要特定的语句(if、case)来判断选择执行;
    循环执行则需要特定的循环控制体来控制(for、while、until)

  • read
    -p 指定要显示的提示
    -s 静默输入,不显示输入的字符
    -n N指定输入的字符长度N
    -d ‘字符’输入结束符
    -t N TIMEOUT为N秒
    read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量
    read -p “Enter a filename : ” FILE

  • 选择执行

    • if
  • 循环执行(for、while、until)
    循环就是程序按照一定的条件反复进行执行相关操作,直到不再满足循环条件时结束;

    • for、while:当型循环,条件为真时循环,条件为假时退出;
      until :直到型循环,条件为假时循环,条件为真时退出;

    • 3种循环比较,循环主要有2种结构

    • Shell脚本编程

      从上面流程图,显然可以看出while循环是”当型的”,until循环是”直到的”

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

(0)
ss
上一篇 2017-04-13
下一篇 2017-04-14

相关推荐

  • 浅谈Linux终端类型

    Linux终端类型 作者:任飞鹏            日期:2016-10-13 终端是什么: 终端(Terminal)也称终端设备,是计算机网络中处于网络最外围的设备,主要用于用户信息的输入以及处理结果的输出等。 早期计算机系统中,由于计算机主机…

    Linux干货 2016-10-19
  • 程序包的编译安装

    程序包的编译安装     程序包的编译安装是比较重要的内容,在之后的网络知识以及服务的配置等学习方面也发挥着重要作用,是我们的必备技能。 一、杂项知识整理 1、which –skip-alias:跳过别名,直接查看原命令 [root@localhost ~]# which –…

    Linux干货 2016-08-24
  • N25第5周作业(grep和find使用)

    显示当前系统上root, fedora 或user1的默认shell 找出/etc/rc.d/init.d/functions文件中某单词后面跟一组小括号的行,形如:hello(); 使用echo命令输出一个绝对路径,使用grep取出基名,扩展取出其路径名 找出IFCONIFG命令结果的1-255之间的数字 挑战题:写一个模式,能匹配出合理的IP地址 挑战题…

    Linux干货 2016-12-30
  • 六步建立yum仓库

    建立yum仓库

    Linux干货 2018-03-26
  • 磁盘文件挂载与卸载

    挂载(mount)何为挂载?挂载指将文件系统与根文件系统的某个现存的目录建立起来的关联关系,这样我们就可以将目录作为访问磁盘文件的入口,进行存取交互。挂载点:挂载点指的是被挂载的对象,通常挂载点是一个目录,不过有时候也有文件作为挂载点格式:mount 设备 挂载点 ;此挂载方法味临时挂载,只在当前的shell中有效,退出则清除挂载关联设备文件在/dev/sd…

    Linux干货 2017-04-24
  • Linux磁盘管理基础

    Linux磁盘管理基础 硬盘结构 文件系统与MBR、GTP 磁盘管理三步骤:分区、格式化、挂载 mount 硬盘结构 硬盘的基本组成材质是盘片,不同容量硬盘的盘片数不等。每个盘片有两面,都可记录信息。盘片表面上以盘片中心为圆心,不同半径的同心圆称为磁道,不同盘片相同半径的磁道所组成的圆柱称为柱面,每个磁道被分成许多扇形的区域,每个区域叫一个扇区,每个扇区可存…

    Linux干货 2016-09-01

评论列表(2条)

  • renjin
    renjin 2017-04-21 11:07

    主要介绍了bash编程的变量,循环语句,判断语句,内容写的很不详细,排版也非常好,继续努力 !

  • Lakeisha
    Lakeisha 2017-04-24 05:25

    16Mi6rion,Exastem muitas marcas sérias, mas todos os dias surgem pedidos de ‘vamos fazer um post em troca de um bloquinho?’ e coisas do tipo.Não sei como tem gente que cai nessas.Concordo contigo q tá faltando uma boa dose de respeito!Beijo grande,