• Linux shell脚本


    一、shell入门

    1.1 介绍

    shell是一个命令解释器,它的作用是解释执行用户输入的命令以及程序等。用户每输入一条命令,shell就执行一条。这种从键盘输入命令,就可以立即得到回应的对话方式,称为交互的方式。

    当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,该程序文件就被称为shell脚本。 在shell脚本里内置了很多命令、语句及循环控制,然后将这些命令一次性执行完毕,这种通过文件执行脚本的方式称为非交互的方式。 

    1.2 shell脚本类型

    shell脚本语言是弱类型语言,无需定义变量类型即可使用,在unix/linux中主要有两大类shell:

    • Bourne shell:包括Bourne shell(sh)、Korn shell(ksh)、Bourne again shell;
    • C shell:包括csh、tcsh两种类型;

    查看系统默认的shell:echo $SHELL

    查看系统支持的shell:cat /etc/shells

    [root@bogon194 ~]# echo  $SHELL
    /bin/bash
    [root@bogon194 ~]# cat  /etc/shells
    /bin/sh
    /bin/bash
    /sbin/nologin
    /usr/bin/sh
    /usr/bin/bash
    /usr/sbin/nologin
    [root@bogon194 ~]#

    1.3 shell脚本的执行

    shell脚本的执行通常可以采用以下几种方式:

    • bash filename或sh filename:这是当脚本文件本身没有执行权限时常使用的方法;
    • /path/filename或./filename:当前路径下执行脚本,需要将脚本文件的权限改为可执行。然后使用脚本的绝对路径或相对路径就可以直接执行脚本了;
    • source filename或.filename: 这种方法通常是使用source或 “.”(点号)读入或加载指定的shell脚本文件,然后依次执行指定的Shell脚本中的语句。这些语句将在当前父 shell 脚本进程中执行(其他几种模式都会启用新的进程执行该脚本进程)。

    1.4 shell脚本编写规范

    shell脚本的开发规范及习惯非常重要,虽然这些规范不是必须要遵守的,但是有了好的规范和习惯,可以大大提高开发效率,并能在后期降低对脚本的维护成本。

    • 一个规范的shell脚本在第一行会指出由那个解释器来执行脚本中的内容,这一行内容在linux bash的编程一般为:#! /bin/bash 或 #! /bin/sh,bash和sh的区别,sh为bash的软连接,大多数情况下,脚本使用:#! /bin/bash 和 #! /bin/sh是没有区别的。
    • 在shell脚本中,跟在 # 后面的内容表示注释,用来对脚本进行注释说明,注释部分不会被当做程序来执行,仅仅是给开发者和使用者看的,系统解释器是看不到的,更不会执行。注释可以自成一行,也可以跟在脚本命令的后面与命令在同一行。 注释尽量不要使用中文,在脚本中最好也不要有中文。
    • shell脚本的开头加版本、版权等信息。
    • shell脚本的命名应以.sh为扩展名。
    • 成对的符号应尽量一次性写出来,然后退格在符号内增加内容,以防止遗漏。这些成对的符号包括: {}、[]、‘’、“”  等。
    • 中括号[]两端至少要有1个空格,因此,键入中括号时即留出空格[  ],然后在退格键入中间内容,并确保两端都至少由一个空格。
    • 对于流程控制语句,应一次性将格式写完,再添加内容。 如:一次性完成for循环语句的格式:
    for
    do
         内容
    done
    • 通过缩进让代码更易读,如:
    if 条件内容     
           then         
                内容 
    fi
    • 脚本中的单引号、双引号及反引号必须为英文状态下的符号。

    二、变量

    简单地说,变量就是用一个固定的字符串(也可能是字符、数字等的组合)代替更多、更复杂的内容,该内容里可能还会包含变量、路径、字符串等其他内容。 变量是暂时存储数据的地方及数据标记,所存储的数据存在于内存空间中,通过正确地调用内存中变量的名字就可以读取出与变量对应的数据。

    变量的赋值方法为: 先写变量名称,紧接着是= ,最后是值。中间无任何空格。 通过echo命令加上 $变量名,即可输出变量的值。 

    定义变量时变量名建议用大写,如  A=zy     B=99;

    read  -p  “提示信息”   变量名      #交互式赋值方法

    查看变量内容echo $A  或 echo ${A}:

    [root@bogon194 shell]# A=zy
    [root@bogon194 shell]# B=99
    [root@bogon194 shell]# echo $A
    zy
    [root@bogon194 shell]# echo ${A}
    zy
    [root@bogon194 shell]# read -p "please input C:" C
    please input C:9999
    [root@bogon194 shell]# echo $C
    9999

    2.1 赋值时使用引号

    • 双引号:允许通过$符号引用其它变量的值;
    • 单引号:禁止引用其它变量的值,$视为普通字符;
    • ``:命令替换,提取命令执行后的输出结果;
    • $():同``;
    [root@bogon194 shell]# A=10
    [root@bogon194 shell]# echo $A
    10
    [root@bogon194 shell]# B=$A+10
    [root@bogon194 shell]# echo $B
    10+10
    [root@bogon194 shell]# C="$A+20"
    [root@bogon194 shell]# echo $C
    10+20
    [root@bogon194 shell]# D='$A+30'
    [root@bogon194 shell]# echo $D
    $A+30
    [root@bogon194 shell]# E=`ls`
    [root@bogon194 shell]# echo $E
    shell.sh

    需要注意的是shell 原生bash不支持简单的数学运算,所说义$A+10为10+10。

     

    命令替换(``、$())与变量替换(${})差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。

     

     

     

    2.2 位置参数

    位置参数是一种在调用 shell 程序的命令行中按照各自的位置决定的变量,是在程序名之后输入的参数。 位置参数之间用空格分隔,shell取第一个位置参数替换程序文件中的 $1,第二个替换 $2 , 依次类推。$0 是一个特殊变量,它的内容是当前这个shell程序的文件名,所以 $0 不是一个位置参数。
    假如我现在有一个 1.sh脚本文件,内容如下:

    #! /bin/bash
    echo $0
    echo $1
    echo $(($2+$3))

    当我执行时,我在文件名后加3个参数:

    [root@bogon194 shell]# sh 1.sh 5 10 20
    1.sh
    5
    30

    这里的数值运算可以先忽略,后面会介绍。

    2.3 预定义变量

    预定义变量和环境变量相类似,也是在shell一开始就定义的变量,不同的是,用户只能根据shell的定义来使用这些变量,所有预定义变量都是由符号“$”和另一个符号组成。 常见的Shell预定义变量有以下几种。

    • $# :位置参数的数量;
    • $* :所有位置参数的内容;
    • $? :命令执行后返回的状态,0表示没有错误,非0表示有错误;
    • $$ :当前进程的进程号;
    • $! :后台运行的最后一个进程号;
    • $0 :当前执行的进程名(即shell程序的文件名);
    • $@ 传递给脚本或函数的所有参数。被双引号" "包含时,与 $* 稍有不同,下面将会讲到。

    假如我现在有一个 2.sh脚本文件,内容如下:

    #!/bin/bash
    echo "File Name: $0"
    echo "First Parameter : $1"
    echo "First Parameter : $2"
    echo "Quoted Values: $@"
    echo "Quoted Values: $*"
    echo "Total Number of Parameters : $#"

    当我执行时:

    $sh 2.sh Zara Ali
    File Name : 2.sh
    First Parameter : Zara
    Second Parameter : Ali
    Quoted Values: Zara Ali
    Quoted Values: Zara Ali
    Total Number of Parameters : 2

    $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号" "包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。 但是当它们被双引号" "包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

    下面的例子可以清楚的看到 $* 和 $@ 的区别:

    #!/bin/bash
    echo "$*=" $*
    echo ""$*"=" "$*"
    echo "$@=" $@
    echo ""$@"=" "$@"
    echo "print each param from $*"
    for var in $*
    do
        echo "$var"
    done
    echo "print each param from $@"
    for var in $@
    do
        echo "$var"
    done
    echo "print each param from "$*""
    for var in "$*"
    do
        echo "$var"
    done
    echo "print each param from "$@""
    for var in "$@"
    do
        echo "$var"
    done

    执行 sh 2.sh "a" "b" "c" "d",看到下面的结果:

    $*=  a b c d
    "$*"= a b c d
    $@=  a b c d
    "$@"= a b c d
    print each param from $*
    a
    b
    c
    d
    print each param from $@
    a
    b
    c
    d
    print each param from "$*"
    a b c d
    print each param from "$@"
    a
    b
    c
    d

    三、算术运算

    shell中常见的算术运算符:

    算术运算符 意义
    +、-、*、/、% 加法、减法、乘法、除法、取余
    ** 幂运算
    ++、-- 增加及减少
    !、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)
    <、<=、>、>= 比较符号(小于、小于等于、大于、大于等于)
    ==、!= 比较符号(相等、不等于)
    =、+=、-= 赋值运算符、例如a+=1等价于a=a+1

    shell中常见的算数运算命令:

    运算操作符及运算命令 意义
    (()) 用于整数运算的常见运算符、效率很高
    let 用于整数运算、类似于(())
    expr 可用于整数运算,但还有很多其他功能
    bc linux下的一个计算器程序
    $[] 用于整数运算

    3.1 (())数值运算命令的用法

    双小括号(())的作用是进行数值运算与数值比较,它的效率很高,用法灵活,其操作方式如下:

    运算操作符与运算命令 意义
    ((i=i+1)) 运算后赋值,即将i+1的运算结果赋值给变量i。注意,不能用echo ((i=i+1))的形式输出表达式的值,但可以使用echo $((i=i+1))输出其值
    i=$(($A+5)) 可以在(())前加$,表示将表达式$A+5与运算后的值赋值给i
    ((8>7&&5==5)) 可以进行比较操作,还可以加入逻辑与和逻辑或,用于条件判断,if ((8>7&&5==5))
    echo $((2+1)) 需要直接输出运算表达式的运算结果时,可以在(())前加$

    3.2 let运算符的用法

    let运算命令的语法格式为: let 赋值表达式  ;

    let 赋值表达式的功能等同于“((赋值表达式))” ;

    [root@bogon194 shell]# i=1
    [root@bogon194 shell]# let i=i+1
    [root@bogon194 shell]# echo $i
    2

    3.3 expr命令的用法

    expr用于计算:

    语法:expr 表达式

    示例:expr 2 + 2、expr 2 - 2 、expr 2 / 2

    注意:运算符号和数字之间要有空格!!

    [root@bogon194 shell]# expr 2 + 2
    4
    [root@bogon194 shell]# expr 2 - 2
    0
    [root@bogon194 shell]# expr 2 * 2
    4
    [root@bogon194 shell]# expr 2 / 2
    1

    expr配合变量进行计算:

    expr在shell中可配合变量进行计算,但需要用反引号将计算表达式括起来。

    [root@bogon194 shell]# i=5
    [root@bogon194 shell]# i=`expr $i + 5`
    [root@bogon194 shell]# echo $i
    10

    利用expr计算字符串的长度:

    [root@bogon194 shell]# char="hello"
    [root@bogon194 shell]# expr length $char
    5

    3.4 bc命令的用法

    bc 是UNIX/Linux下的计算器,除了作为计算器来使用,还可以作为命令行计算工具使用。

    3.5 $[]运算符

    $[]用于整数运算,示例如下:

    [root@bogon194 shell]# echo  $[2-5]
    -3
    [root@bogon194 shell]# echo  $[2+5]
    7

    四、条件测试

    通常,在shell的各种条件结构和流程控制结构中都要进行各种测试,然后根据测试结果执行不同的操作,有时候也会与 if 等条件语句相结合,来完成测试判断,以减少程序运行错误。

    几种条件测试语句:

    条件测试语法 说明
    test 测试表达式 利用test命令进行条件表达式测试
    [测试表达式] 通过[]进行条件表达式测试
    [[测试表达式]] 通过[[]]进行条件表达式测试
    ((测试表达式)) 通过(())进行条件表达式测试,一般用于if语法

    测试表达式 test 、[] 、[[]] 、 (()) 的区别:

    测试表达式符号 test [] [[]] (())
    边界是否需要空格 需要 需要 需要 不需要
    逻辑操作符 ! 、-a、 -o ! 、-a、 -o ! 、&& 、 || ! 、&& 、 ||
    整数比较操作符 -eq 、 -gt 、-lt、-ge 、-le -eq 、 -gt 、-lt、-ge 、-le -eq 、 -gt 、-lt、-ge 、-le 或  = 、>  、< 、 >= 、 <= = 、>  、< 、 >= 、 <=
    字符串比较操作符 = 、 == 、!= = 、 == 、!= = 、 == 、!= 不支持
    文件操作 -d、-f、-e、-r、-s、-w、-x、-L、-nt、-ot -d、-f、-e、-r、-s、-w、-x、-L、-nt、-ot -d、-f、-e、-r、-s、-w、-x、-L、-nt、-ot 不支持
    是否支持通配符匹配 不支持 不支持 不支持 不支持

    4.1 文件测试操作符

    常用文件测试操作符 说明
    -d   , d的全拼为 directory 文件存在且为目录则为真
    -f   ,   f的全拼为  file 文件存在且为文件则为真
    -e , e的全拼为 exists 文件存在则为真
    -s ,s的全拼为 size 文件存在且大小不为0则为真
    -r ,r的全拼为 read 文件存在且可读则为真
    -w ,w的全拼为write 文件存在且可写则为真
    -x ,x的全拼为executable 文件存在且可执行则为真
    -L ,L的全拼为link 文件存在且为链接文件则为真
    f1 -nt  f2  ,nt的全拼为 newer than 文件f1比文件f2新则为真
    f1 -ot f2 ,ot的全拼为older than 文件f1比文件f2旧则为真

    test测试:

    [root@bogon194 shell]# test -d  1.sh && echo true || echo false
    false
    [root@bogon194 shell]# test -f  1.sh && echo true || echo false
    true
    [root@bogon194 shell]# test -e  1.sh && echo true || echo false
    true

    []测试:

    [root@bogon194 shell]# [ -d 1.sh ] && echo true || echo false
    false
    [root@bogon194 shell]# [ -f 1.sh ] && echo true || echo false
    true

    [[]]测试:

    [root@bogon194 shell]# [[ -d 1.sh ]] && echo true || echo false
    false
    [root@bogon194 shell]# [[ -f 1.sh ]] && echo true || echo false
    true

    4.2 字符串测试操作符

    常用字符串测试操作符 说明
    -n 若字符串长度不为0,则为真
    -z 若字符串长度为0,则为真
    “字符串1”  ==  “字符串2” 若字符串1等于字符串2,则为真
    “字符串1”  !=  “字符串2” 若字符串1不等于字符串2,则为真

    注: == 和 !=  两端要有空格 。

    test测试:

    [root@bogon194 shell]# test "zy" == "zy" && echo true || echo false
    true
    [root@bogon194 shell]# test -n "zy"  && echo true || echo false
    true

    []测试:

    [root@bogon194 shell]# [ "zy" == "zy" ]  && echo true || echo false
    true
    [root@bogon194 shell]# [ -n "zy" ]  && echo true || echo false
    true

    [[]]测试:

    [root@bogon194 shell]# [[ "zy" == "zy" ]]  && echo true || echo false
    true
    [root@bogon194 shell]# [[ -n "zy" ]]  && echo true || echo false
    true

    4.3 整数二元比较操作符

    在[]以及test中使用的比较符号

    在(())和[[]]中使用的比较符号

    说明
    -eq ==或= 相等,全拼为  equal
    -ne != 不相等,全拼为 not equal
    -gt > 大于,全拼为 greater than
    -ge >= 大于等于,全拼为 greater equal
    -lt < 小于,全拼为 less than
    -le <= 小于等于 ,全拼为less equal
    • "="和"!="也可以在[]中作比较使用,但在[]中使用包含"<"和">"的符号时,需要用反斜线转义,有时不转义虽然语法不会报错,但是结果可能不对;
    • 可以在[[]]中使用包含“-gt”和“-lt”的符号,但是不建议使用;
    • 比较符号两端也要有空格,[] (()) [[]] 两端都要有空格;

    test使用:

    [root@bogon194 shell]# test 3 -eq 3 && echo true || echo false
    true
    [root@bogon194 shell]# test 3 -eq 4 && echo true || echo false
    false

    []使用:

    [root@bogon194 shell]# [ 3 -eq 3 ] && echo true || echo false
    true
    [root@bogon194 shell]# [ 3 -eq 4 ] && echo true || echo false
    false

    [[]]使用:

    [root@bogon194 shell]# [[ 3 == 3 ]] && echo true || echo false
    true
    [root@bogon194 shell]# [[ 3 == 4 ]] && echo true || echo false
    false

    (())使用:

    [root@bogon194 shell]# (( 3 == 3 )) && echo true || echo false
    true
    [root@bogon194 shell]# (( 3 == 4 )) && echo true || echo false
    false

    4.4 逻辑操作符

    在[]和test中使用的操作符 在[[]]和(())中使用的操作符 说明
    -a && and ,与,两端都为真,才为真
    -o || or ,或, 两端有一个为真,就为真
    ! ! not ,非, 两端相反,则结果为真

    4.5 if条件判断语句

    简单条件判断:

    #####单条件判断##############
    if  条件判断
    then 
          命令
    else
          命令
    fi
     
    #
     
    if  条件判断;then 
         命令
    else
         命令
    fi

    案例如下3.sh:

    #! /bin/bash
    read -p "please input number:" i
    if [ $i -gt 5 ]
    then
            echo true
    else
            echo false
    fi

    执行:

    [root@bogon194 shell]# sh 3.sh 9
    please input number:12
    true

    双重条件判断:

    ###双条件判断#####
    if 条件判断
    then
          命令
    elif 条件判断
    then 
          命令
    else
       命令
    fi
     
    ##或
    if 条件判断;then
        命令
    elif 条件判断;then 
        命令
    else
        命令
    fi

    4.6 case条件判断语句

    case条件语句相当于多分支的if/elif/ellse条件语句,但是它比这些条件语句看起来更规范更工整,常被应用于实现系统服务启动脚本等企业应用场景中。

    case  变量  in
            one)
                命令
    ;;
            two)
                 命令
    ;;
             *) 
                 命令
    esac

     测试用例4.sh:

    read -p "please input a number or str:" i
    case $i in
            [1-9])
                    echo "this a number"
    ;;
            [a-z])
                    echo "this is a litter str"
    ;;
            *)
                    echo "this is a dont known"
    esac

    执行结果:

    [root@bogon194 shell]# sh 4.sh
    please input a number or str:2
    this a number
    [root@bogon194 shell]# sh 4.sh
    please input a number or str:d
    this is a litter str
    [root@bogon194 shell]# sh 4.sh
    please input a number or str:&
    this is a dont known

    4.7 for循环语句

    语法格式:

    for  条件
    do
       命令
    done
     
    ##或
    for  条件;do
       命令
    done

    4.8 while循环语句

    语法格式:

    while  条件
    do
       命令
    done

    4.9 break、continue、exit 循环控制语句

    break 、continue在条件语句及循环语句(for、while、if等)中用于控制程序走向;而exit则用于终止所有语句并退出当前脚本。

    命令 说明
    break n 如果省略 n ,则表示跳出整个循环,n 表示跳出循环的成熟
    continue n 如果省略 n ,则表示跳过本次循环,忽略本次循环的剩余代码,进行循环的下一次循环。n表示退到第 n 层继续循环
    exit n  退出当前 shell 程序,n 为上一次程序执行的状态返回值。n 也可以省略,在下一个 shell 里可通过 $? 接收 exit n 的n值

    下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,就要使用break命令。

    #!/bin/bash
    while :
    do
        echo -n "Input a number between 1 to 5: "
        read aNum
        case $aNum in
            1|2|3|4|5) echo "Your number is $aNum!"
            ;;
            *) echo "You do not select a number between 1 to 5, game is over!"
                break
            ;;
        esac
    done

    在嵌套循环中,break 命令后面还可以跟一个整数,表示跳出第几层循环。例如:

    break n

    表示跳出第 n 层循环。

    下面是一个嵌套循环的例子,如果 var1 等于 2,并且 var2 等于 0,就跳出循环:

    #!/bin/bash
    for var1 in 1 2 3
    do
       for var2 in 0 5
       do
          if [ $var1 -eq 2 -a $var2 -eq 0 ]
          then
             break 2
          else
             echo "$var1 $var2"
          fi
       done
    done

    如上,break 2 表示直接跳出外层循环。运行结果:

    1 0
    1 5

    continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

    对上面的例子进行修改:

    #!/bin/bash
    while :
    do
        echo -n "Input a number between 1 to 5: "
        read aNum
        case $aNum in
            1|2|3|4|5) echo "Your number is $aNum!"
            ;;
            *) echo "You do not select a number between 1 to 5!"
                continue
                echo "Game is over!"
            ;;
        esac
    done

    运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句:

    echo "Game is over!"

    永远不会被执行。

    同样,continue 后面也可以跟一个数字,表示跳出第几层循环。

    #!/bin/bash
    NUMS="1 2 3 4 5 6 7"
    for NUM in $NUMS
    do
       Q=`expr $NUM % 2`
       if [ $Q -eq 0 ]
       then
          echo "Number is an even number!!"
          continue
       fi
       echo "Found odd number"
    done

    运行结果:

    Found odd number
    Number is an even number!!
    Found odd number
    Number is an even number!!
    Found odd number
    Number is an even number!!
    Found odd number

    五、数组

    在shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:

      array_name=(value1 ... valuen)

    例如:

    array_name=(value0 value1 value2 value3)

    还可以单独定义数组的各个分量:

    array_name[0]=value0
    array_name[1]=value1
    array_name[2]=value2

    可以不使用连续的下标,而且下标的范围没有限制。

    读取数组元素值的一般格式是:

     ${array_name[index]}

    例如:

    valuen=${array_name[2]}

    获取数组长度的方法与获取字符串长度的方法相同,例如:

    # 取得数组元素的个数
    length=${#array_name[@]}
    # 或者
    length=${#array_name[*]}
    # 取得数组单个元素的长度
    lengthn=${#array_name[n]}

    六、echo

    echo是Shell的一个内部指令,用于在屏幕上打印出指定的字符串。命令格式:

    echo arg

    6.1 显示转义字符

    echo ""It is a test""

    输出:

    "It is a test"

    6.2 显示变量

    name="OK"
    echo "$name It is a test"

    输出:

    OK It is a test

    同样双引号也可以省略。

    如果变量与其它字符相连的话,需要使用大括号{ }:

    mouth=8
    echo "${mouth}-1-2009"

    结果将是:

    8-1-2009

    6.3 显示结果重定向至文件

    echo "It is a test" > myfile

    6.4 原样输出字符串

    若需要原样输出字符串(不进行转义),请使用单引号。例如:

    echo '$name"'

    6.5 显示命令执行结果

    echo `date`

    七 函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,shell 也支持函数。shell 函数必须先定义后使用。

    7.1 函数定义

    shell 函数的定义格式如下:

    function_name () {
        list of commands
        [ return value ]
    }

    函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。

    shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。

    如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

    先来看一个例子:

    #!/bin/bash
    # Define your function here
    Hello () {
       echo "Url is http://see.xidian.edu.cn/cpp/shell/"
    }
    # Invoke your function
    Hello

    调用函数只需要给出函数名,不需要加括号。

    再来看一个带有return语句的函数:

    #!/bin/bash
    funWithReturn(){
        echo "The function is to get the sum of two numbers..."
        echo -n "Input first number: "
        read aNum
        echo -n "Input another number: "
        read anotherNum
        echo "The two numbers are $aNum and $anotherNum !"
        return $(($aNum+$anotherNum))
    }
    funWithReturn
    # Capture value returnd by last command
    ret=$?
    echo "The sum of two numbers is $ret !"

    运行结果:

    The function is to get the sum of two numbers...
    Input first number: 25
    Input another number: 50
    The two numbers are 25 and 50 !
    The sum of two numbers is 75 !

    像删除变量一样,删除函数可以使用 unset 命令,不过要加上 .f 选项,如下所示:

    $unset .f function_name

    如果你希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用。

    7.2 函数传参

    在shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...

    带参数的函数示例:

    #!/bin/bash
    funWithParam(){
        echo "The value of the first parameter is $1 !"
        echo "The value of the second parameter is $2 !"
        echo "The value of the tenth parameter is $10 !"
        echo "The value of the tenth parameter is ${10} !"
        echo "The value of the eleventh parameter is ${11} !"
        echo "The amount of the parameters is $# !"  # 参数个数
        echo "The string of the parameters is $* !"  # 传递给函数的所有参数
    }
    funWithParam 1 2 3 4 5 6 7 8 9 34 73

    运行脚本:

    The value of the first parameter is 1 !
    The value of the second parameter is 2 !
    The value of the tenth parameter is 10 !
    The value of the tenth parameter is 34 !
    The value of the eleventh parameter is 73 !
    The amount of the parameters is 12 !
    The string of the parameters is 1 2 3 4 5 6 7 8 9 34 73 !"

    注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

    八、输入输出重定向

    Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。

    8.1 输出重定向

    命令的输出不仅可以是显示器,还可以很容易的转移向到文件,这被称为输出重定向。

    命令输出重定向的语法为:

    command > file

    这样,输出到显示器的内容就可以被重定向到文件。

    例如,下面的命令在显示器上不会看到任何输出:

     who > users

    打开 users 文件,可以看到下面的内容:

    [root@bogon194 shell]# cat users
    root     pts/0        2021-09-28 15:17 (10.80.12.52)
    root     pts/2        2021-09-28 16:26 (10.80.12.52)

    输出重定向会覆盖文件内容,请看下面的例子:

    [root@bogon194 shell]# echo line 1 > users
    [root@bogon194 shell]# cat users
    line 1

    如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾。

    8.2 输入重定向

    和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:

    command < file

    这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

    注意:输出重定向是大于号(>),输入重定向是小于号(<)。

    例如,计算 users 文件中的行数,可以使用下面的命令:

    [root@bogon194 shell]# wc -l users
    1 users

    也可以将输入重定向到 users 文件:

    [root@bogon194 shell]# wc -l < users
    1

    注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。

    8.3 重定向深入讲解

    一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

    • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
    • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
    • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

    默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
    如果希望 stderr 重定向到 file,可以这样写:

    command 2 > file

    如果希望 stderr 追加到 file 文件末尾,可以这样写:

    command 2 >> file

    2 表示标准错误文件(stderr)。

    如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

    command > file 2>&1

    command >> file  2>&1

    这里的&没有固定的意思,放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符。换言之 2>1 代表将stderr重定向到当前路径下文件名为1的regular file中,而2>&1代表将stderr重定向到文件描述符为1的文件(即/dev/stdout)中,这个文件就是stdout在file system中的映射。

    如果希望对 stdin 和 stdout 都重定向,可以这样写:

    command < file1 >file2

    command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。 

    全部可用的重定向命令列表
    命令说明
    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 之间的内容作为输入。

    8.4 /dev/null 文件

    如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

    command > /dev/null

    /dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

    如果希望屏蔽 stdout 和 stderr,可以这样写:

    command > /dev/null  2>&1

    九、xargs

    xargs(英文全拼: eXtended ARGuments)是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。

    xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。

    xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。

    xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。

    xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。

    之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要,所以就有了 xargs 命令,例如:

    find /sbin -perm +700 |ls -l       #这个命令是错误的
    find /sbin -perm +700 |xargs ls -l   #这样才是正确的

    xargs 一般是和管道一起使用。

    somecommand |xargs -item  command

    xargs 用作替换工具,读取输入数据重新格式化后输出。

    定义一个测试文件,内有多行文本数据:

    # cat test.txt
    
    a b c d e f g
    h i j k l m n
    o p q
    r s t
    u v w x y z

    多行输入单行输出:

    # cat test.txt | xargs
    a b c d e f g h i j k l m n o p q r s t u v w x y z

    参考文章:

    [1]Linux中编写Shell脚本

    [2]shell语法

  • 相关阅读:
    闰年测试
    EditBox的测试用例设计
    测试工程中的评审
    测试框架
    github
    第一次上机实验
    对软件测试的初步认识
    白盒测试
    Date : 日期对象
    C++ 格式化输出 及 输入 流
  • 原文地址:https://www.cnblogs.com/zyly/p/15323917.html
Copyright © 2020-2023  润新知