; Shell脚本编程 | Linux运维部落

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种结构

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

原创文章,作者:s,如若转载,请注明出处:/73285

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论列表(2条)

  • renjin
    renjin 2017-04-21 11:07

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

  • Lakeisha 2017-04-24 05:25

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

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1660809109@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班

友情链接:万达娱乐直属  万达娱乐平台  万达注册  万达娱乐开户  guoqibee.com  万达娱乐主管QQ  万达招商  万达直属  万达娱乐主管