• shell脚本的基本使用


    本文是对菜鸟教程 shell编程原文 的总结并记录 如有侵权 联系删除

    简介

    说明:

    Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。而shell脚本 则是 为shell程序编写的脚本,业界所说的 shell 通常都是指 shell 脚本

    常见shell 程序:

    • Bourne Again Shell(/bin/bash,linux默认)

    • Bourne Shell(/usr/bin/sh或/bin/sh,unix默认)

      ......

    通常 并不区分 Bourne Again Shell 和 Bourne Shell,所以像 #!/bin/sh,它同样也可以改为 #!/bin/bash。

    Hello,World

    #!/bin/bash
    echo "Hello World !"
    

    #! 是一个约定的标记,它告诉系统这个脚本需要什么哪个 shell程序执行

    echo 输出打印

    执行脚本:

    将 代码保存为 test.sh,

    chmod +x ./test.sh  #使脚本具有执行权限
    ./test.sh  #执行脚本
    

    一定要写成 ./test.sh 如果直接写成 test.sh,则会去PATH 环境里找

    也可以作为 解释器的参数:

    /bin/sh test.sh
    

    变量

    1. 定义一个变量

    name="Hello,World"
    

    注意事项:

    • 命名只能使用英文字母, 数字 和下划线,收个字母不能为数字
    • 中间不能有空格 可以用 _ 下划线
    • 不能使用标点符号
    • 不能使用bash里的关键字

    用语句给变量赋值:

    for file in `ls /etc`
    或
    for file in $(ls /etc)
    

    将 /etc 下的目录 的文件夹名循环出来

    2. 使用变量:

    name="Hello,World"
    echo $name
    echo ${name}
    

    变量名的 花括号是可选的 加不加都行, 加了更方便解释器识别变量的边界,建议都加上

    已定义的变量可以重新定义

    name="tom"
    echo $name
    name="jack"
    echo $name
    

    3.只读变量

    name="tom"
    readonly name
    name="jack"
    

    运行脚本报错信息:./test.sh: line 4: name: readonly variable

    4.删除变量

    用关键字 unset 删除变量 删除后的变量不能使用 不能删除 只读变量

    name="Hello,World"
    unset name
    echo $name
    

    运行脚本 没有任何输出

    5.变量类型

    shell脚本在 运行时 同时存在三种变量

    • 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
    • 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
    • 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    6.字符串

    可以用单引号 双引号 也可以不用引号定义

    单引号

    str='is a string'

    单引号中的任何字符都会原样输出,所有不能引用其他变量 ${other}

    不能出现 一个单引号 无法转义,但如果成对出现 则代表拼接

    双引号

    name='tom'
    str="Hello, I know you are "$name"!"
    echo  $str
    

    运行输出:

    Hello, I know you are "tom"! 
    

    可以转义 可以引用变量

    常用函数

    string="abcd"
    echo ${#string} # 获取长度 输出 4
    echo ${string:1:2} # 截取从1下标开始截取2个字符 输出 bc
    echo `expr index "$string" bc`  #获取b或c在子串中的出现在第几位 输出 2
    

    数组

    bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

    定义数组: 数组名=(值1 值2 ... 值n) 括号表示数组 元素用空格隔开

    array_name=(value0 value1 value2 value3)
    

    或者

    array_name=(
    value0
    value1
    value2
    value3
    )
    

    读取数组:

    value=${array_name[n]} # 读取下标为 n的
    echo ${array_name[@]} # 用 @ 符号 获取所有元素
    
    length=${#array_name[@]} #获取数组长度
    length=${#array_name[*]} #获取数组长度
    lengthn=${#array_name[n]}# 获取 单个元素的长度
    

    注释

    上面已经反复使用了 以# 开头就是 注释内容

    多行注释

    :<<EOF
    注释内容...
    注释内容...
    注释内容...
    EOF
    
    ###EOF也可以换成其他 符号
    
    :<<'
    注释内容...
    注释内容...
    注释内容...
    '
    
    :<<!
    注释内容...
    注释内容...
    注释内容...
    !
    

    传递参数

    我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数

    其中 $0 默认为文件名 传不传都有

    echo "文件名:$0"
    echo "第一个参数为:$1"
    echo "第二个参数为:$2"
    echo "第三个参数为:$3"
    

    执行脚本 ./test.sh 1 2 3 输出

    执行的文件名:./test.sh
    第一个参数为:1
    第二个参数为:2
    第三个参数为:3
    

    还有一些默认的参数可以获取:

    符号 描述
    $# 传递到脚本的参数个数
    $* 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
    $$ 脚本运行的当前进程ID号
    $! 后台运行的最后一个进程的ID号
    $@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
    $- 显示Shell使用的当前选项,与set命令功能相同。
    $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

    $* 与$@ 区别:都是引用所有参数 但当 用双引号 时 $* 代表 拼接在一起,$@ 则代表 为一个数组

    运算符

    原生bash不支持简单的数学运算,但是可以通过其他命令来实现,比如 expr,

    expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

    val=`expr 2 + 2`
    echo $val # 4
    

    注意:

    1. 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
    2. 完整的表达式要被 **\` \`** 包含,esc下面 ,不是单引号
    

    支持的运算符:

    运算符 说明 举例
    + 加法 expr $a + $b 结果为 30。
    - 减法 expr $a - $b 结果为 -10。
    * 乘法 expr $a * $b 结果为 200。(转义 * 是关键字)
    / 除法 expr $b / $a 结果为 2。
    % 取余 expr $b % $a 结果为 0。
    = 赋值 a=$b 将把变量 b 的值赋给 a。
    == 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
    != 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。

    条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]

    关系运算符

    关系运算符只支持数字 不支持 字符串 除非 字符串可以强转为 数字 : "4"

    假设 a为10 b为 20

    运算符 说明 举例
    -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
    -ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
    -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
    -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
    -ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
    -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

    布尔运算符

    只能作用于布尔值

    假定a 为 10, b 为 20:

    运算符 说明 举例
    ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
    -o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
    -a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

    逻辑运算符

    也是判断布尔值的 关系 必须用 [[]] 双括号(不用报错 但貌似也能解析)

    假定a 为 10, b 为 20:

    运算符 说明 举例
    && 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
    || 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

    字符串运算符

    比较字符串 假定a 为 "abc", b 为 "def":

    运算符 说明 举例
    = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
    != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
    -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
    -n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ] 返回 true。
    $ 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

    printf 命令

    类似于echo 命令都是打印字符串 但要比echo功能更加强大,

    语法: printf format-string [arguments...]

    ​ format 为 待格式化的字符串

    ​ arguments 为 参数

    格式化占位符有 %s %c %d %f ,

    实例:

    # 输出 郭靖     杨过   郭芙  
    # %-10s: 10代表占10个字符 - 号代表右对齐,没有就是左对齐
    # 不足的字符空格补齐
    printf "%-10s %-8s %-4s
    " 郭靖 杨过 郭芙 
    
    # 输出:郭芙     女      47.99
    # %f 代表 格式化小数  4.2 中的 0.2 代表的就是 保留两位小数
    printf "%-10s %-8s %-4.2f
    " 郭芙 女 47.9876 
    
    # 输出结果;abcdef  没有引号也可以输出
    printf %s abcdef
    
    #输出结果 abcdef ,格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用(没有换行符 所以连在一起)
    printf %s abc def
    
    #结果 : abc
    #      def
    printf "%s
    " abc def
    
    # 输出 :  and 0
    # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
    printf "%s and %d 
    " 
    

    test命令

    Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

    数值测试

    参数 说明
    -eq 等于则为真
    -ne 不等于则为真
    -gt 大于则为真
    -ge 大于等于则为真
    -lt 小于则为真
    -le 小于等于则为真

    实例:

    # 输出 两个数相等!
    num1=100
    num2=100
    if test $[num1] -eq $[num2]
    then
        echo '两个数相等!'
    else
        echo '两个数不相等!'
    fi
    

    字符串测试

    参数 说明
    = 等于则为真
    != 不相等则为真
    -z 字符串 字符串的长度为零则为真
    -n 字符串 字符串的长度不为零则为真

    实例:

    ## 两个字符串不相等!
    num1="tom1"
    num2="tom2"
    if test $num1 = $num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
    

    文件测试

    参数 说明
    -e 文件名 如果文件存在则为真
    -r 文件名 如果文件存在且可读则为真
    -w 文件名 如果文件存在且可写则为真
    -x 文件名 如果文件存在且可执行则为真
    -s 文件名 如果文件存在且至少有一个字符则为真
    -d 文件名 如果文件存在且为目录则为真
    -f 文件名 如果文件存在且为普通文件则为真
    -c 文件名 如果文件存在且为字符型特殊文件则为真
    -b 文件名 如果文件存在且为块特殊文件则为真

    实例:

    ##文件已存在!
    cd /bin
    if test -e ./bash
    then
        echo '文件已存在!'
    else
        echo '文件不存在!'
    fi
    

    test 后面也可以用 ( -a )、或( -o )、非( ! )三个逻辑操作符 拼接多个 条件

    流程控制

    if语句

    语法格式:

    if condition
    then
        command1 
        command2
        ...
        commandN 
    fi
    

    实例:

    #!/bin/bash
    a=20
    b=20
    
    if a=b
    then
    	echo "ab相等"
    fi
    
    ## 输出: ab相等
    

    if else 语句

    语法格式:

    if condition
    then
        command1 
        command2
        ...
        commandN
    else
        command
    fi
    

    实例:

    #!/bin/bash
    a=10
    b=20
    
    if a=b
    then
    	echo "ab相等"
    else
    	echo "ab不想等"
    fi
    
    ## 输出: ab不相等
    

    if else-if else 语句

    语法格式:

    if condition1
    then
        command1
    elif condition2 
    then 
        command2
    else
        commandN
    fi
    

    实例:

    #!/bin/bash
    a=10
    b=20
    
    if a=b
    then
    	echo "ab相等"
    elif a!=b
    then
    	echo "ab不想等"
    else
    	echo "没有符合的条件"
    fi
    
    ## 输出: ab不相等
    

    for循环

    语法:

    for var in item1 item2 ... itemN
    do
        command1
        command2
        ...
        commandN
    done
    

    实例:

    for loop in 1 2 3 4 5
    do
        echo "The value is: $loop"
    done
    #输出  
    # The value is: 1
    # The value is: 2
    # The value is: 3
    # The value is: 4
    # The value is: 5
    
    #输出字符串中的字符
    for str in 'This is a string'
    do
        echo $str
    done
    
    ##输出: This is a string
    
    

    while语句

    语法:

    while condition
    do
        command
    done
    

    实例:

    #如果int值大于5则退出循环 使用let命令使int自增 
    
    #!/bin/bash
    int=1
    while(( $int<=5 ))
    do
        echo $int
        let "int++"
    done
    
    #输出:  
    # 1
    # 2
    # 3
    # 4
    # 5
    

    until循环

    和 while 类似 但是 却又完全相反 ,,当条件为true时 停止循环体

    语法:

    until condition
    do
        command
    done
    

    实例:

    #!/bin/bash
    a=0
    until [ ! $a -lt 5 ]
    do
       echo $a
       let "a++"
    done
    
    # 输出:
    # 0
    # 1
    # 2
    # 3
    # 4
    

    上面说了三个循环方式

    无限循环:

    while :
    do
        command
    done
    #或者
    while true
    do
        command
    done
    #或者
    for (( ; ; ))
    

    跳出循环:

    break 和 continue. 和java类似 一个是跳出整个循环体 一个仅仅只是跳出本次循环

    case语句

    多选择语句,一个值匹配一个模式

    语法:

    当 值 与模式匹配后 将执行 后面所有的命令,直到 ;; 结束, 可以在结尾 以 * 接收任何值,如果前面都没匹配的话

    case 值 in
    模式1)
        command1
        command2
        ...
        commandN
        ;;
    模式2)
        command1
        command2
        ...
        commandN
        ;;
    esac
    

    实例:

    aNum=1
    case $aNum in
        1)  echo 'aNum的值是 1'
        ;;
        2)  echo 'aNum的值是 2'
        ;;
        3)  echo 'aNum的值是 3'
        ;;
        4)  echo 'aNum的值是 4'
        ;;
        *)  echo '其他'
        ;;
    esac
    
    # 输出:  aNum的值是 1
    

    函数

    自定义函数,在函数声明后的地方就可以调用了.

    语法:

    funname ()
    
    {
         command1
        ...
    }
    

    方法内可以return 返回结果 如果没有return 则方法内的最后一条命令的结果作为返回值

    demoFun(){
        echo "这是一个函数!"
    }
    demoFun
    
    ## 输出 : 这是一个函数!
    

    一个带return语句的函数: 函数返回值在调用该函数后通过 $? 来获得。

    funWithReturn(){
       a=1
       b=2
        return $(($a+$b))
    }
    funWithReturn
    echo "输入的两个数字之和为 $? !"
    
    # 输出: 输入的两个数字之和为 3 !
    

    一个带参数的函数:通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数

    当参数个数>= 10 时 需要用 ${n} : ${10}引用

    funWithParam(){
        echo "第一个参数为 $1 !"
        echo "第二个参数为 $2 !"
    }
    funWithParam 1 2 
    
    #输出结果;
    # 第一个参数为 1 !
    # 第二个参数为 2 !
    

    默认的参数取值方式:

    参数处理 说明
    $# 传递到脚本或函数的参数个数
    $* 以一个单字符串显示所有向脚本传递的参数
    $$ 脚本运行的当前进程ID号
    $! 后台运行的最后一个进程的ID号
    $@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
    $- 显示Shell使用的当前选项,与set命令功能相同。
    $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

    Shell 输入/输出重定向

    可以读取终端内的文件数据,也可以将数据写入到文件

    常用命令:

    命令 说明
    command > file 将输出重定向到 file。
    command < file 将输入重定向到 file。
    command >> file 将输出以追加的方式重定向到 file。
    n > file 将文件描述符为 n 的文件重定向到 file。
    n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
    n >& m 将输出文件 m 和 n 合并。
    n <& m 将输入文件 m 和 n 合并。
    << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

    输出重定向:

    语法: command1 > file1

    实例 : echo "Hello" > temp

    将打印的字符串 输出到 本目录下的 temp文件 ,没有会创建,如果有内容 会直接覆盖

    如果不希望被覆盖 则可以使用 : command1 >> file1 是以追加的方式写入

    输入重定向:

    语法: command1 < file1

    实例: 统计temp文件 内的行数

    wc -l temp  # 输出 1 temp  行数和文件名
    wc -l < temp # 输出 1 没有文件名,因为它只读取内容
    

    也可以输入输出结合使用:

    command1 < infile > outfile  # 同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。
    

    文件包含

    一个脚本 包含另一个脚本,可以封装一些公用的代码

    语法:

    . filename   # 注意点号(.)和文件名中间有一空格
    
    或
    
    source filename
    

    实例:

    test1.sh :

    a="hello"
    

    test2.sh :

    #引入本目录下的 test1 脚本
    . ./test1.sh
    echo a  # 输出 hello
    
  • 相关阅读:
    详解RTMP协议视频直播点播平台EasyDSS转推视频直播流到CDN(云直播)
    RTMP协议视频直播点播平台EasyDSS如何实现RTSP视频流地址加密?
    阿里王坚:“城市大脑”开启算力时代
    数据中心网络测试自动化的逐步发展
    在数据中心利用AI的5个理由
    基于层次过滤的文本生成
    解密为何 Go 能从众多语言中脱颖而出
    乔姆斯基专访:深度学习并没有探寻世界本质
    释放数据价值的「三个关键点」
    改改Python代码,运行速度还能提升6万倍,Science:先别想摩尔定律了
  • 原文地址:https://www.cnblogs.com/xjwhaha/p/13598663.html
Copyright © 2020-2023  润新知