• 第14章 Linux的shell编程


    文档配套视频讲解链接地址

    1. 腾讯课堂视频链接地址 : 51_Shell编程_Shell变量1
    2. 腾讯课堂视频链接地址 : 52_Shell编程_read与test命令2
    3. 腾讯课堂视频链接地址 : 53_Shell编程_小节复习.3
    4. 腾讯课堂视频链接地址 : 54_Shell编程_控制语句4
    5. 腾讯课堂视频链接地址 : 55_Shell编程_小节复习5
    6. 腾讯课堂视频链接地址 : 56_Shell编程_Shell函数6

    第14章 Shell编程

    14.1 Shell简介

    随着各式Linux系统的图形化程度的不断提高,用户在桌面环境下,通过点击、拖拽等操作就可以完成大部分的工作。

    然而,许多Ubuntu Linux功能使用Shell命令来实现,要比使用图形界面交互,完成的更快、更直接

    英文单词Shell可直译为“贝壳”。“贝壳”是动物作为外在保护的一种工具。

    可以这样认为,Linux中的Shell就是Linux内核的一个外层保护工具,并负责完成用户与内核之间的交互

    命令是用户向系统内核发出控制请求,与之交互的文本流。

    Shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互。

    同时,Shell为操作系统提供了内核之上的功能,直接用来管理和运行系统。

    当需要重复执行若干命令,可以将这些命令集合起来,加入一定的控制语句,编辑成为Shell脚本文件,交给Shell批量执行。

    1. Shell交互过程
    1. 用户在命令行提示符下键入命令文本,开始与Shell进行交互。

    2. 接着,Shell将用户的命令或按键转化成内核所能够理解的指令

    3. 控制操作系统做出响应,直到控制相关硬件设备。

    4. 然后,Shell将输出结果通过Shell提交给用户。

    image-20220829102905379

    2. 选择Shell

    最初的UNIX Shell经过多年的发展,由不同的机构、针对不同的目的,开发出许多不同类型的Shell程序。目前流行的Shell主要有几种 :

    Bourne Shell(简称sh):Bourne Shell由AT&T贝尔实验室的S.R.Bourne开发,也因开发者的姓名而得名。它是Unix的第一个Shell程序,早已成为工业标准。目前几乎所有的Linux系统都支持它。不过Bourne Shell的作业控制功能薄弱,且不支持别名与历史记录等功能。目前大多操作系统是将其作为应急Shell使用。

    C Shell(简称csh):C Shell由加利福尼亚大学伯克利分校开发。最初开发的目的是改进Bourne Shell的一些缺点,并使Shell脚本的编程风格类似于C语言,因而受到广大C程序员的拥护。不过C Shell的健壮性不如Bourne Shell。

    Korn Shell(简称ksh):Korn Shell由David Korn开发,解决了Bourne Shell的用户交互问题,并克服了C Shell的脚本编程怪癖的缺点。Korn Shell的缺点是需要许可证,这导致它应用范围不如Bourne Shell广泛。

    Bourne Again Shell(简称bash):Bourne Again Shell由AT&T贝尔实验室开发,是Bourne Shell的增强版。随着几年的不断完善,已经成为最流行的Shell。它包括了早期的Bourne Shell和Korn Shell的原始功能,以及某些C Shell脚本语言的特性。此外,它还具有以下特点:能够提供环境变量以配置用户Shell环境,支持历史记录,内置算术功能,支持通配符表达式,将常用命令内置简化。

    2. 编译型语言与解释型语言

    编译型语言:需要使用编译器进行编译,之后才可以执行的语言 , 源文件是不能直接执行的

    常用的编译型语言有: c , c++,java,c# ,vb , asm, go

    解释型语言:不需要编译, 直接可以运行的语言, 源文件可以直接运行的语言

    常用的解释性语言有: python , javascript ,PHP, sql , shell, html

    Shell脚本(角色扮演的剧本, 角本,脚本)语言是解释型语言。

    Shell脚本的本质:Shell命令的有序集合。

    14.2 shell 编程的基本过程

    1. 第一步

    建立 shell 文件, shell 文件的后缀名是.sh , 或则不写

    包含任意多行操作系统命令或shell命令的文本文件

    1. 赋予shell文件执行权限 (x)

    用chmod命令修改权限;

    1. 执行shell文件

    直接在命令行上调用shell程序

    例如:

    • 源文件
    02-linuxbase/01-hello.sh
    
    • 1
    • 源代码
    #! /bin/bash
    
    # 第一句话 表示那个可执行程序来解析shell 命令 
    
    echo "hello world!!"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 运行结果
    linux@ubuntu:~$ ls
    Desktop  Documents  Downloads  Music  Pictures  Public  snap  Templates  Videos  work
    linux@ubuntu:~$ cd work/
    linux@ubuntu:~/work$ ls
    02-linuxbase
    linux@ubuntu:~/work$ cd 02-linuxbase/
    linux@ubuntu:~/work/02-linuxbase$ ls
    linux@ubuntu:~/work/02-linuxbase$ vi 01-hello.sh
    linux@ubuntu:~/work/02-linuxbase$ ls -l 01-hello.sh 
    -rw-rw-r-- 1 linux linux 103 829 10:49 01-hello.sh
    linux@ubuntu:~/work/02-linuxbase$ ./01-hello.sh
    bash: ./01-hello.sh: 权限不够
    linux@ubuntu:~/work/02-linuxbase$ chmod a+x 01-hello.sh 
    linux@ubuntu:~/work/02-linuxbase$ ls -l 01-hello.sh 
    -rwxrwxr-x 1 linux linux 103 829 10:49 01-hello.sh
    linux@ubuntu:~/work/02-linuxbase$ ./01-hello.sh 
    hello world!!
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    14.3 Shell变量

    Shell允许用户建立变量存储数据,但不支持数据类型(整型、字符、浮点型),将任何赋给变量的值都解释为一串字符

    Variable=value     # 等号的左边和右边不能有空格
    
    • 1

    命名规则同C语言中的命名规则

    count=1
    echo $count    # $ 访问变量中的值 
    DATE=`date`    #  反引号 是取变量的输出
    echo $DATE
    
    • 1
    • 2
    • 3
    • 4

    运行结果

    linux@ubuntu:~/work/02-linuxbase$ DATE=`date`
    linux@ubuntu:~/work/02-linuxbase$ $DATE
    2022年:未找到命令
    linux@ubuntu:~/work/02-linuxbase$ echo $DATE
    2022年 08月 29日 星期一 11:12:17 CST
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Bourne Shell有如下四种变量

    • 用户自定义变量

    • 位置变量即 命令行参数

    • 预定义变量

    • 环境变量

    1. 用户自定义变量

    在shell编程中通常使用全大写变量,方便识别

    $ COUNT=1
    
    • 1

    变量的调用:在变量前加$

    $ echo $COUNT 
    
    • 1

    Linux Shell/bash从右向左赋值

    $Y=y
    $ X=$Y
    $ echo $X 
    y 
    
    • 1
    • 2
    • 3
    • 4

    使用unset命令删除变量的赋值

    $ Z=hello 
    $ echo $Z 
    hello 
    $ unset Z 
    $ echo $Z 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    2. 位置变量
    $0  与键入的命令行一样,包含脚本文件名
    $1,$2,……$9  分别包含第一个到第九个命令行参数
    $#   包含命令行参数的个数
    $@   包含所有命令行参数:“$1,$2,……$9$?   包含前一个命令的退出状态
    $*   包含所有命令行参数:“$1,$2,……$9$$   包含正在执行进程的ID号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    例如:

    • 源文件
    02-weizhi.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    echo "0=$0" 
    echo "1=$1" 
    echo "2=$2" 
    echo "3=$3" 
    echo "4=$4" 
    echo "5=$5" 
    echo "6=$6" 
    echo "7=$7" 
    echo "8=$8" 
    echo "9=$9" 
    echo "10=$10" 
    echo "11=$11" 
    
    echo "#=$#"
    echo "@=$@"
    echo "*=$*"
    
    ls 
    echo "ls -> ?=$?"   # 上一条命令执行的结果 0:成功 , 1 失败 
    
    cd /haha
    echo "cd /haha -> ?=$?"   # 上一条命令执行的结果 0:成功 , 1 失败 
    
    echo "$ =$$"   # 程序的进程号 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh
    0=./weizhi.sh
    1=
    2=
    3=
    4=
    5=
    6=
    7=
    8=
    9=
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    0=./weizhi.sh
    1=s1
    2=s2
    3=s3
    4=s4
    5=s5
    6=s6
    7=s7
    8=s8
    9=s9
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    0=./weizhi.sh
    1=s1
    2=s2
    3=s3
    4=s4
    5=s5
    6=s6
    7=s7
    8=s8
    9=s9
    10=s10
    11=s11
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    0=./weizhi.sh
    1=s1
    2=s2
    3=s3
    4=s4
    5=s5
    6=s6
    7=s7
    8=s8
    9=s9
    10=s10
    11=s11
    #=11
    linux@ubuntu:~/work/02-linuxbase$ vi weizhi.sh
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    0=./weizhi.sh
    1=s1
    2=s2
    3=s3
    4=s4
    5=s5
    6=s6
    7=s7
    8=s8
    9=s9
    10=s10
    11=s11
    #=11
    @=s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    linux@ubuntu:~/work/02-linuxbase$ 
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh 
    0=./weizhi.sh
    1=
    2=
    3=
    4=
    5=
    6=
    7=
    8=
    9=
    10=0
    11=1
    #=0
    @=
    01-hello.sh  weizhi.sh
    ls -> ?=0
    ./weizhi.sh: 第 23 行: cd: /haha: 没有那个文件或目录
    cd /haha -> ?=1
    linux@ubuntu:~/work/02-linuxbase$ ./weizhi.sh s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    0=./weizhi.sh
    1=s1
    2=s2
    3=s3
    4=s4
    5=s5
    6=s6
    7=s7
    8=s8
    9=s9
    10=s10
    11=s11
    #=11
    @=s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    *=s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11
    01-hello.sh  weizhi.sh
    ls -> ?=0
    ./weizhi.sh: 第 24 行: cd: /haha: 没有那个文件或目录
    cd /haha -> ?=1
    $ =2732
    linux@ubuntu:~/work/02-linuxbase$ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    3. 常用shell环境变量
    HOME: /etc/passwd文件中列出的用户主目录 
    IFS:Internal Field Separator, 默认为空格,tab及换行符
    PATH :shell搜索路径
    PS1PS2:默认提示符($)及换行提示符(>) 
    TERM:终端类型,常用的有vt100,ansi,vt200,xterm等 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实例23

    • 输出环境变量的值

    • 源程序

    03-huanjing.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    echo "HOME=$HOME"
    echo "PATH=$PATH"
    echo "PS1=$PS1"
    echo "PS2=$PS2"
    echo "TERM=$TERM"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./03-huanjing.sh 
    HOME=/home/linux
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
    PS1=
    PS2=
    TERM=xterm-256color
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    14.4 shell 控制语句

    1. Shell程序

    shell 程序由零或多条shell语句构成。 shell语句包括三类:说明性语句、功能性语句和结构性语句。

    说明性语句: 以#号开始到该行结束,不被解释执行

    功能性语句: 任意的shell命令、用户程序或其它shell程序。

    结构性语句:条件测试语句、多路分支语句、循环语句、循环控制语句等。

    说明性语句 必不可少的: #! /bin/bash

    2. 输入与输出

    输出: echo

    输入: read

    read 命令
    read 从标准输入读入一行, 并赋值给后面的变量, 等价于c语言的scanf 
    其语法为:
      	read  var
    把读入的数据全部赋给var
    	read  var1  var2  var3
    把读入行中的第一个单词(word)赋给var1, 第二个单词赋给var2, ……把其余所有的词赋给最后一个变量.
    如果执行read语句时标准输入无数据, 则程序在此停留等侯, 直到数据的到来或被终止运行。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    实例24

    • 源文件
    04-read.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    echo -n "please input 1 number >:"  # -n 的意思是, 去除\n, echo 不输出\n
    read var1 
    
    echo "var1 = $var1"
    
    echo -n "please input 3 number >:"
    read var1 var2 var3 
    
    echo "var1 = $var1"
    echo "var2 = $var2"
    echo "var3 = $var3"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./04-read.sh 
    please input 1 number >:123
    var1 = 123
    please input 3 number >:89
    var1 = 89
    var2 = 
    var3 = 
    linux@ubuntu:~/work/02-linuxbase$ ./04-read.sh 
    please input 1 number >:1
    var1 = 1
    please input 3 number >:123 9 7 
    var1 = 123
    var2 = 9
    var3 = 7
    linux@ubuntu:~/work/02-linuxbase$ ./04-read.sh 
    please input 1 number >:123
    var1 = 123
    please input 3 number >:1 2 3 4 5 5 6 76 7 
    var1 = 1
    var2 = 2
    var3 = 3 4 5 5 6 76 7
    linux@ubuntu:~/work/02-linuxbase$ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    3. expr 命令

    算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、乘(\*)、整除(/)和求模(%)等操作。

    实例25:

    • 计算2个数的加减乘除求余
    • 源文件
    05-expr.sh
    
    • 1
    • 源代码
    #! /bin/bash
    
    echo -n "please input 2 number >:"
    read num1 num2
    echo "num1=$num1 , num2=$num2"
    
    ret=`expr $num1 + $num2`
    echo "$num1 + $num2 = $ret"
    
    ret=`expr $num1 - $num2`
    echo "$num1 - $num2 = $ret"
    
    ret=`expr $num1 \* $num2`
    echo "$num1 * $num2 = $ret"
    
    ret=`expr $num1 / $num2`
    echo "$num1 / $num2 = $ret"
    
    ret=`expr $num1 % $num2`
    echo "$num1 % $num2 = $ret"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./05-expr.sh 
    please input 2 number >:10 15
    num1=10 , num2=15
    10 + 15 = 25
    10 - 15 = -5
    10 * 15 = 150
    10 / 15 = 0
    10 % 15 = 10
    linux@ubuntu:~/work/02-linuxbase$ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    4. test命令

    test语句可测试三种对象:

    ​ 字符串 整数 文件属性

    1. 字符串测试
    s1 = s2     测试两个字符串的内容是否完全一样
    s1 != s2    测试两个字符串的内容是否有差异
    -z s1       测试s1 字符串的长度是否为0
    -n s1       测试s1 字符串的长度是否不为0
    
    • 1
    • 2
    • 3
    • 4
    1. 整数测试
    a -eq b         测试a 与b 是否相等    # ==
    a -ne b         测试a 与b 是否不相等  #  != 
    a -gt b         测试a 是否大于b       # > 
    a -ge b         测试a 是否大于等于b   # >=
    a -lt b         测试a 是否小于b      # <
    a -le b         测试a 是否小于等于b   # <=
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 测试文件
    -e FILE    测试一个文件或目录时候存在 
    -d name    测试name 是否为一个目录
    -f name     测试name 是否为普通文件
    -L name    测试name 是否为符号链接
    -r name     测试name 文件是否存在且为可读
    -w name     测试name 文件是否存在且为可写
    -x name     测试name 文件是否存在且为可执行
    -s name     测试name 文件是否存在且其长度不为0
    f1 -nt f2   测试文件f1 是否比文件f2 更新
    f1 -ot f2   测试文件f1 是否比文件f2 更旧
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实例26:

    • 测试2个字符串的关系
    • 源文件
    06-test-str.sh
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    echo -n "please input 2 string >:"
    read s1 s2
    echo "s1=$s1 , s2=$s2"
    
    if test -z $s1    # 判断s1字符串的长度不为0  
    then 
        echo "s1 is empty"
        exit 1
    fi 
    
    if test -z $s2    # 判断s1字符串的长度不为0  
    then 
        echo "s2 is empty"
        exit 1
    fi 
    
    if test $s1 = $s2 
    then 
        echo "$s1 = $s2"
    else 
        echo "$s1 != $s2"
    fi 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./06-test-str.sh 
    please input 2 string >:goodbye hello
    s1=goodbye , s2=hello
    goodbye != hello
    linux@ubuntu:~/work/02-linuxbase$ ./06-test-str.sh 
    please input 2 string >:goodbye goodbye
    s1=goodbye , s2=goodbye
    goodbye = goodbye
    linux@ubuntu:~/work/02-linuxbase$ ./06-test-str.sh
    please input 2 string >:
    s1= , s2=
    s1 is empty
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实例27:

    • 从终端输入的y/n , 读取用户输入的是y还是n
    • 源文件
    07-test-yes-no.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    echo -n "please input [y/n] >:"
    read s1 
    echo "s1=$s1"
    
    if test -z $s1    # 判断s1字符串的长度不为0  
    then 
        echo "s1 is empty"
        exit 1
    fi 
    
    if test $s1 = "y" 
    then 
        echo "yes"
    fi 
    if test $s1 = "n" 
    then 
        echo "no"
    fi 
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./07-test-yes-no.sh 
    please input [y/n] >:y
    s1=y
    yes
    linux@ubuntu:~/work/02-linuxbase$ ./07-test-yes-no.sh 
    please input [y/n] >:n
    s1=n
    no
    linux@ubuntu:~/work/02-linuxbase$ ./07-test-yes-no.sh 
    please input [y/n] >:
    s1=
    s1 is empty
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    实例28

    • 输入2个数, 比较2个数之间的关系(> , >= , <, <=, ==, != )

    • 源文件

    08-test-numer.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    echo -n "please input 2 number >:"
    read n1  n2 
    echo "n1=$n1 , n2=$n2"
    
    
    if test $n1 -gt $n2  # >  
    then 
        echo "$n1 > $n2"
    fi 
    
    if test $n1 -ge $n2   # >= 
    then 
        echo "$n1 >= $n2"
    fi 
    
    if test $n1 -lt $n2   # < 
    then 
        echo "$n1 < $n2"
    fi 
    
    if test $n1 -le $n2   # <= 
    then 
        echo "$n1 <= $n2"
    fi 
    
    if test $n1 -eq $n2   # == 
    then 
        echo "$n1 == $n2"
    fi 
    
    if test $n1 -ne $n2   # != 
    then 
        echo "$n1 != $n2"
    fi 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./08-test-numer.sh 
    please input 2 number >:10 20
    n1=10 , n2=20
    10 < 20
    10 <= 20
    10 != 20
    linux@ubuntu:~/work/02-linuxbase$ ./08-test-numer.sh 
    please input 2 number >:10 10 
    n1=10 , n2=10
    10 >= 10
    10 <= 10
    10 == 10
    linux@ubuntu:~/work/02-linuxbase$ ./08-test-numer.sh 
    please input 2 number >:10 8
    n1=10 , n2=8
    10 > 8
    10 >= 8
    10 != 8
    linux@ubuntu:~/work/02-linuxbase$
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    实例29

    • 测试文件的属性 , 文价是否存在 , 文件的类型(BCD-LSP), 文件的读写权限(rwx)
    • 源文件
    09-test-file.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    echo -n "please input filename >:"
    read  filename 
    echo "filename=$filename"
    
    if ! test -e $filename   # 文件不存在则报错  
    then 
        echo "file not existed"
        exit 1
    fi 
    
    if test -b $filename   # 块设备文件 
    then 
        echo "block"
    elif test -c $filename  # 字符设备文件
    then 
        echo "character"
    elif test -d $filename  #目录 
    then 
        echo "directory"
    elif test -h $filename   # 符号链接
    then 
        echo "link"
    elif test -f $filename   # 普通文件
    then 
        echo "regular"
    elif test -S $filename   # socket文件 
    then 
        echo "socket"
    elif test -p $filename   # pipe文件 
    then 
        echo "pipe"
    fi
    
    
    if test -r $filename   # 可读 
    then 
        echo "read"
    fi
    
    if test -w $filename   # 可写 
    then 
        echo "write"
    fi
    
    if test -x $filename   # 可执行 
    then 
        echo "exec"
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:/
    filename=/
    directory
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:/dev/sda
    filename=/dev/sda
    block
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:/dev/vca
    filename=/dev/vca
    file not existed
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:/dev/vcs
    filename=/dev/vcs
    character
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:09-test-file.sh
    filename=09-test-file.sh
    regular
    linux@ubuntu:~/work/02-linuxbase$ ln -s 09 09-test-file.sh 
    ln: 无法创建符号链接'09-test-file.sh': 文件已存在
    linux@ubuntu:~/work/02-linuxbase$ ln -s 09-test-file.sh  09
    linux@ubuntu:~/work/02-linuxbase$ ls -l 09
    lrwxrwxrwx 1 linux linux 15 830 10:41 09 -> 09-test-file.sh
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:09
    filename=09
    regular
    linux@ubuntu:~/work/02-linuxbase$ vi 09-test-file.sh 
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:09
    filename=09
    link
    linux@ubuntu:~/work/02-linuxbase$ mkfifo myfifo
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:myfifo
    filename=myfifo
    pipe
    linux@ubuntu:~/work/02-linuxbase$ 
    linux@ubuntu:~/work/02-linuxbase$ ./09-test-file.sh 
    please input filename >:09-test-file.sh
    filename=09-test-file.sh
    regular
    read
    write
    exec
    linux@ubuntu:~/work/02-linuxbase$ 
    linux@ubuntu:~/work/02-linuxbase$ ls -l 09-test-file.sh 
    -rwxrwxr-x 1 linux linux 792 830 10:46 09-test-file.sh
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    5. test命令的替代写法[]

    在程序中可以 使用 [ ] 替代test 命令 , 这种用法就是 test 的缩写

    实例30

    • 把实例29的test命令用[ ] 替代
    • 源文件
    10-test-file.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    echo -n "please input filename >:"
    read  filename 
    echo "filename=$filename"
    
    if ! [ -e $filename ]  # 文件不存在则报错  
    then 
        echo "file not existed"
        exit 1
    fi 
    
    if [ -b $filename ]   # 块设备文件 
    then 
        echo "block"
    elif test -c $filename  # 字符设备文件
    then 
        echo "character"
    elif [ -d $filename ] #目录 
    then 
        echo "directory"
    elif [ -h $filename ]  # 符号链接
    then 
        echo "link"
    elif [ -f $filename ] # 普通文件
    then 
        echo "regular"
    elif [ -S $filename ]  # socket文件 
    then 
        echo "socket"
    elif [ -p $filename ]  # pipe文件 
    then 
        echo "pipe"
    fi
    
    
    if [ -r $filename ]  # 可读 
    then 
        echo "read"
    fi
    
    if [ -w $filename ]  # 可写 
    then 
        echo "write"
    fi
    
    if [ -x $filename ]  # 可执行 
    then 
        echo "exec"
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./10-test-file.sh 
    please input filename >:/
    filename=/
    directory
    read
    exec
    linux@ubuntu:~/work/02-linuxbase$ ./10-test-file.sh 
    please input filename >:09-test-file.sh
    filename=09-test-file.sh
    regular
    read
    write
    exec
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    6. 条件语句 if … then …fi

    语法结构:

    if    表达式
    then  
    		命令表
    fi     
    
    • 1
    • 2
    • 3
    • 4

    如果表达式为真, 则执行命令表中的命令; 否则退出if语句, 即执行fi后面的语句。

    if和fi是条件语句的语句括号, 必须成对使用;

    命令表中的命令可以是一条, 也可以是若干条。

    7. 条件语句 if…then…else…fi

    语法结构为:

    if      表达式
    then 
    	命令表1
    else  
    	命令表2
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果表达式为真, 则执行命令表1中的命令;

    否则执行命令表2中的语句.

    8. 条件语句 if…then…elif … then … else…fi

    语法结构为:

    if     表达式1
    then   
    	命令表1
    elif   表达式2
    then   
    	命令表2 
    else   
    	命令表3 
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果表达式1为真, 则执行命令表1中的命令, 再退出if语句;

    否则执行命令表2中的语句, 再退出if语句.

    9. 多路分支语句 case…esac

    多路分支语句case用于多重条件测试, 语法结构清晰自然. 其语法为:

     case   字符串变量   in
                模式1)
                           命令表1
                            ;;   # 这个分号不能少 
                模式2)
                           命令表2
                            ;;
                 ……
                模式n)
                           命令表n
                            ;;
                 *)
                ;;
    
     esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    实例31

    • 输入成绩的水平(A/B/C/D/E), 转换成成绩的范围
    • 源文件
    11-case.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    
    echo -n "please input your level(A/B/C/D/E) >:"
    read level 
    echo "level = $level"
    
    
    case  $level  in 
        "A")
            echo "90 =< score <=100"
            ;;
        "B")
            echo "80 =< score < 90"
            ;;
        "C")
            echo "70 =< score < 80"
            ;;
        "D")
            echo "60 =< score < 70"
            ;;
        "E")
            echo " 0 =< score < 60"
            ;;
        *)
            ;;
    esac
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:A
    level = A
    90 =< score <=100
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:B
    level = B
    80 =< score < 90
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:C
    level = C
    70 =< score < 80
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:D
    level = D
    60 =< score < 70
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:E
    level = E
     0 =< score < 60
    linux@ubuntu:~/work/02-linuxbase$ ./11-case.sh 
    please input your level(A/B/C/D/E) >:8
    level = 8
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    10. for…do…done

    当循环次数已知或确定时, 使用for循环语句来多次执行一条或一组命令。 循环体由语句括号do和done来限定。

    格式为:

    for  变量名  in  单词表
    do
      命令表
    done
    
    • 1
    • 2
    • 3
    • 4

    变量依次取单词表中的各个单词, 每取一次单词, 就执行一次循环体中的命令. 循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条。

    实例32

    • 源文件
    12-for.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    mylist=`ls`
    
    if ! [ -e hello ]  # 判断当前目录下, hello目录是否存在
    then 
        mkdir hello 
    fi 
    
    for file in $mylist 
    do 
        if [ $file != hello ]    # 如果文件名不是hello , 就复制, 是就不复制了
        then 
            cp $file hello 
        fi 
    
    done 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./12-for.sh 
    linux@ubuntu:~/work/02-linuxbase$ ls
    01-hello.sh   03-huanjing.sh  05-expr.sh      07-test-yes-no.sh  09-test-file.sh  11-case.sh  hello
    02-weizhi.sh  04-read.sh      06-test-str.sh  08-test-numer.sh   10-test-file.sh  12-for.sh
    linux@ubuntu:~/work/02-linuxbase$ ls hello/
    01-hello.sh   03-huanjing.sh  05-expr.sh      07-test-yes-no.sh  09-test-file.sh  11-case.sh
    02-weizhi.sh  04-read.sh      06-test-str.sh  08-test-numer.sh   10-test-file.sh  12-for.sh
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    11. 循环语句 while…do…done

    语法结构为:

    while     命令或表达式
    do
    	命令表
    done
    
    • 1
    • 2
    • 3
    • 4

    while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。

    while语句的退出状态为命令表中被执行的最后一条命令的退出状态。

    实例32:

    • 计算1+2+3+4+…+100 之和
    • 源文件
    13-while.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    i=0
    sum=0
    while  [ $i -lt 100 ] 
    do 
        i=`expr $i + 1 `    # i = i + 1 
        echo "i=$i"
        sum=`expr $sum + $i `
    done
    echo "sum=$sum"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./13-while.sh 
    i=1
    i=2
    i=3
    i=4
    i=5
    i=6
    ...
    i=89
    i=90
    i=91
    i=92
    i=93
    i=94
    i=95
    i=96
    i=97
    i=98
    i=99
    i=100
    sum=5050
    linux@ubuntu:~/work/02-linuxbase$
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    12. 循环语句 until…do…done

    语法结构为:

    until   命令或表达式
    do
    	命令表
    done
    
    • 1
    • 2
    • 3
    • 4

    until循环与while循环的功能相似, 所不同的是只有当测试的命令或表达式的值是假时, 才执行循环体中的命令表, 否则退出循环. 这一点与while命令正好相反.

    实例34

    • 计算1+2+3+4+…+100 之和
    • 源文件
    14-until.sh
    
    • 1
    • 源代码
    #! /bin/bash
    
    i=0
    sum=0
    until ! [ $i -lt 100 ] 
    do 
        i=`expr $i + 1 `    # i = i + 1 
        echo "i=$i"
        sum=`expr $sum + $i `
    done
    echo "sum=$sum"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./14-until.sh 
    i=1
    i=2
    i=3
    i=4
    i=5
    i=6
    ...
    i=90
    i=91
    i=92
    i=93
    i=94
    i=95
    i=96
    i=97
    i=98
    i=99
    i=100
    sum=5050
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    13. break 和 continue

    break n 则跳出n层;

    continue语句则马上转到最近一层循环语句的下一轮循环上,

    continue n则转到最近n层循环语句的下一轮循环上.

    实例35

    • 计算一天有多少秒
    • 源文件
    15-break-continue.sh
    
    • 1
    • 源代码
    #! /bin/bash
    
    sec=0
    min=0
    hour=0
    count_sec=0
    while  true 
    do 
        echo "HH:MM:SS -> $hour:$min:$sec"
        count_sec=`expr $count_sec + 1`
        sec=`expr $sec + 1`
        if [ $sec -lt 60 ]
        then 
            continue 
        fi 
        sec=0
        min=`expr $min + 1`
        if [ $min -lt 60 ]
        then 
            continue 
        fi 
        min=0
        hour=`expr $hour + 1`
        if [ $hour -lt 24 ]
        then 
            continue 
        fi 
        hour=0
        break
    
    done  
    echo "count_sec=$count_sec"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 运行结果
    ...
    HH:MM:SS -> 23:59:46
    HH:MM:SS -> 23:59:47
    HH:MM:SS -> 23:59:48
    HH:MM:SS -> 23:59:49
    HH:MM:SS -> 23:59:50
    HH:MM:SS -> 23:59:51
    HH:MM:SS -> 23:59:52
    HH:MM:SS -> 23:59:53
    HH:MM:SS -> 23:59:54
    HH:MM:SS -> 23:59:55
    HH:MM:SS -> 23:59:56
    HH:MM:SS -> 23:59:57
    HH:MM:SS -> 23:59:58
    HH:MM:SS -> 23:59:59
    count_sec=86400
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    14.5 shell 函数

    1. 函数

    ​ 在shell程序中, 常常把完成固定功能、且多次使用的一组命令(语句)封装在一个函数里,每当要使用该功能时只需调用该函数名即可。

    ​ 函数在调用前必须先定义,即在顺序上函数说明必须放在调用程序的前面。

    ​ 调用程序可传递参数给函数, 函数可用return语句把运行结果返回给调用程序。

    ​ 函数只在当前shell中起作用, 不能输出到子Shell中。

    函数定义格式:

    方式一:

    function_name ( )
    {
                command1
                ……
                commandn
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    方式二 :

    function   function_name ( )
    {
                command1
                ……
                commandn
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实例35

    • 使用函数计算2个数的 加减乘除求余
    • 源文件
    16-func.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    
    add()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 + $2`
        return $ret 
    }
    sub()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 - $2`
        return $ret 
    }
    
    mul()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 \* $2`
        return $ret 
    }
    div()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 / $2`
        return $ret 
    }
    yu()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 % $2`
        return $ret 
    }
    
    
    
    echo -n "please input 2 number >:"
    read n1 n2 
    echo "n1=$n1 , n2=$n2"
    
    if [ -z $n1 ] || [ -z $n2 ]
    then 
        echo "n1 or n2 empty"
    fi 
    
    add $n1 $n2     
    # 位置变量
    # $0 = add 
    # $1 = $n1 
    # $2 = $n2
    # 函数的返回值 通过$? 获取 
    echo "$n1 + $n2 = $? "
    
    sub $n1 $n2     
    echo "$n1 - $n2 = $? "
    
    mul $n1 $n2     
    echo "$n1 * $n2 = $? "
    
    div $n1 $n2     
    echo "$n1 / $n2 = $? "
    
    yu $n1 $n2     
    echo "$n1 % $n2 = $? "
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./16-func.sh 
    please input 2 number >:10 4
    n1=10 , n2=4
    1=10
    2=4
    10 + 4 = 14 
    1=10
    2=4
    10 - 4 = 6 
    1=10
    2=4
    10 * 4 = 40 
    1=10
    2=4
    10 / 4 = 2 
    1=10
    2=4
    10 % 4 = 2 
    linux@ubuntu:~/work/02-linuxbase$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    2. 局部变量与全局变量

    声明局部变量的格式:
    local variable_name =value
    全局作用域:在脚本的其他任何地方都能够访问该变量。
    variable_name =value

    实例36

    • 全局变量和局部变量的使用
    • 源文件
    17-global.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    number1=200    # 全局变量
    
    add()
    {
        local number2=100   # 局部变量 
        echo "add:number1=$number1"
        echo "add:number2=$number2"
    
        ret=`expr $1 + $2`
        return $ret 
    }
    
    
    
    echo "number1=$number1"
    echo "number2=$number2"
    
    add  1 2 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./17-global.sh 
    number1=200
    number2=
    add:number1=200
    add:number2=100
    linux@ubuntu:~/work/02-linuxbase$ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    14.6 shell 调试方法

    分析输出的错误信息。

    通过在脚本中加入调试语句,输出调试信息来辅助诊断错误。

    功能:set -x , set +x 跟踪程序的每一步的执行结果

    实例37

    • 源文件
    18-debug.sh 
    
    • 1
    • 源代码
    #! /bin/bash
    
    set -x 
    add()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 + $2`
        return $ret 
    }
    sub()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 - $2`
        return $ret 
    }
    
    mul()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 \* $2`
        return $ret 
    }
    div()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 / $2`
        return $ret 
    }
    yu()
    {
        echo "1=$1"
        echo "2=$2"
        ret=`expr $1 % $2`
        return $ret 
    }
    
    
    
    
    
    
    echo -n "please input 2 number >:"
    read n1 n2 
    echo "n1=$n1 , n2=$n2"
    
    if [ -z $n1 ] || [ -z $n2 ]
    then 
        echo "n1 or n2 empty"
    fi 
    
    add $n1 $n2     
    # 位置变量
    # $0 = add 
    # $1 = $n1 
    # $2 = $n2
    # 函数的返回值 通过$? 获取 
    echo "$n1 + $n2 = $? "
    
    sub $n1 $n2     
    echo "$n1 - $n2 = $? "
    
    mul $n1 $n2     
    echo "$n1 * $n2 = $? "
    
    div $n1 $n2     
    echo "$n1 / $n2 = $? "
    
    yu $n1 $n2     
    echo "$n1 % $n2 = $? "
    
    
    set +x 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 运行结果
    linux@ubuntu:~/work/02-linuxbase$ ./18-debug.sh 
    + echo -n 'please input 2 number >:'
    please input 2 number >:+ read n1 n2
    1 4
    + echo 'n1=1 , n2=4'
    n1=1 , n2=4
    + '[' -z 1 ']'
    + '[' -z 4 ']'
    + add 1 4
    + echo 1=1
    1=1
    + echo 2=4
    2=4
    ++ expr 1 + 4
    + ret=5
    + return 5
    + echo '1 + 4 = 5 '
    1 + 4 = 5 
    + sub 1 4
    + echo 1=1
    1=1
    + echo 2=4
    2=4
    ++ expr 1 - 4
    + ret=-3
    + return -3
    + echo '1 - 4 = 253 '
    1 - 4 = 253 
    + mul 1 4
    + echo 1=1
    1=1
    + echo 2=4
    2=4
    ++ expr 1 '*' 4
    + ret=4
    + return 4
    + echo '1 * 4 = 4 '
    1 * 4 = 4 
    + div 1 4
    + echo 1=1
    1=1
    + echo 2=4
    2=4
    ++ expr 1 / 4
    + ret=0
    + return 0
    + echo '1 / 4 = 0 '
    1 / 4 = 0 
    + yu 1 4
    + echo 1=1
    1=1
    + echo 2=4
    2=4
    ++ expr 1 % 4
    + ret=1
    + return 1
    + echo '1 % 4 = 1 '
    1 % 4 = 1 
    + set +x
    linux@ubuntu:~/work/02-linuxbase$ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
  • 相关阅读:
    数据结构:链式队列
    装饰者模式
    【leetcode】257. 二叉树的所有路径
    Moonbeam于Moonbase Alpha构建新式XCM对EVM跨链功能
    3.【异步通信框架】RabbitMQ
    银行测试人员谈测试需求
    2023年【安全生产监管人员】考试题及安全生产监管人员找解析
    微服务实践k8s与dapr开发部署实验(2)状态管理
    @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
    【保姆级教程】ChatGPT/GPT4科研技术应用与AI绘图
  • 原文地址:https://blog.csdn.net/shengli001842/article/details/127605208