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

相关推荐

  • 脚本及变量解析

    bash脚本编程 脚本文件格式: 第一行顶格:#!bin/bash  (shebang) 注释信息:以#开头 代码注释:好的程序员必备 适量的添加缩进或添加空白行以示分割 语言:编程语言格式:库,算法和数据结构 编程思想:      能够把学到的编程语言的语法格式随时转换为解决问题的思路     &…

    Linux干货 2016-08-12
  • Linux-文件系统挂载:mount的用法

     文件系统挂载  本章详细介绍文件系统挂载、卸载(mount,umount);  如何通过mount命令挂载使用文件系统、挂载常用参数、以及开机自动挂载(/etc/fstab)。    挂载描述:             挂载:将额外文件系…

    2017-06-19
  • 马哥教育网络班22期+第4周课程练习

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。   cp -r /etc/skel /home/tuser1    chmod -R go=— /home/tuser1 2、编辑/etc/group文件,添加组hadoo…

    Linux干货 2016-09-19
  • 第十周 Apache服务

    1、Centos7系统下实现httpd-2.2的安装,并分别实现prefork、worker、event等几种工作方式 2、简述request报文请求方法和状态响应码 3、详细描述httpd虚拟主机、站点访问控制、基于用户的访问控制、持久链接等应用配置实例  

    2018-02-09
  • 复制多台虚拟机及简单的网络配置

    虚拟机的复制,网络地址的简单配置,图形化界面setup和system-config-network的使用

    2017-09-09
  • Linux命令的使用格式及部分常用命令详述

    Linux命令的使用格式及部分常用命令详述 Linux系统中命令的使用格式 Linux中命令的使用遵循以下格式 # COMMAND OPTIONS ARGUMENTS   ###命令 选项 参数,三项之间用空格分开 执行一个命令需要指定需要内核将哪一个二进制程序运行为一个进程,C…

    Linux干货 2016-10-30

评论列表(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,