0%

Shell学习

  1. shell的变量

    变量类型:

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

    变量定义:

    • 定义变量时变量名和等号之间不能有空格
    • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
    • 不能使用标点符号

    实例:

    1
    2
    3
    my_name="hulc"
    readonly url
    unset url

    shell字符串

    shell里定义字符串可以用单引号也可以用双引号

    • 单引号

      • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
      • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
    • 双引号

      • 双引号里可以有变量

      • 双引号里可以出现转义字符

        1
        2
        3
        4
        #!/bin/bash
        my_str="this is a test"
        echo $my_str
        echo "The str is:\$ $my_str "

    字符串长度的获取

    使用**#**获取字符串长度

    1
    2
    string="abcd"
    echo ${#string} #输出 4

    字符串的截断操作

    1
    2
    3
    #从字符串str第一个字符(下标0)开始,截取长度4
    str="this is a test"
    echo ${str:0:4} #输出this

    字符串的查找操作

    1
    2
    str="This is a test"
    echo `expr index "$str" th` #在str里查找字符t或者h,哪个字符先出现就计算哪个,输出结果1

    shell数组

    shell数组有点不同于C语言的数组,其元素类型可以是不同的

    shell里用括号”()”表示数组,数组中元素用空格分开

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 第一种形式
    arr_int1=(1 2 3 4)

    # 第二种形式
    arr_int2[0]=1
    arr_int2[1]=2

    #第三种形式
    arr_int3=(
    1
    2
    3
    4
    )

    数组元素的获取

    • 单个元素获取,使用下标:

      1
      ${arr_name[arr_index]}
    • 获取数组所有元素,使用**@或者***

      1
      2
      3
      ${arr_name[@]}

      ${arr_name[*]}

    数组长度的获取

    ​ 使用#获取数组长度

    1
    2
    3
    4
    5
    arr_int=(1 2 3 4)
    len_arr=${#arr_int[@]}
    len_single=${#arr_int[0]}
    echo "the length of arr_int is:${len_arr}"
    echo "the length of single element is:${len_single}"
  2. shell传递参数

    shell脚本获取传递参数方式如下

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

    $ 与 $@ 区别:*

    • 相同点:都是引用所有参数。
    • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 “ * “ 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)

    实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    for loop1 in "$*"; do
    echo $loop1
    done

    for loop2 in "$@"; do
    echo $loop2
    done
    #第一个loop输出1 2 3
    #第二个loop每行输出一个数字

    注意点:

    • 在为shell脚本传递的参数中如果包含空格,应该使用单引号或者双引号将该参数括起来,以便于脚本将这个参数作为整体来接收(尤其注意在函数的参数传递过程)

      实例:

      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
      #!/bin/bash

      echo "---------------with double quote ---------------"
      echo "$1"
      echo "$2"
      echo "$3"
      function my_procedure1() {
      echo "$1"
      echo "$2"
      echo "$3"
      }
      my_procedure1 "$@"

      echo "---------------withtout double quote ---------------"
      echo $1
      echo $2
      echo $3
      function my_procedure2() {
      echo $1
      echo $2
      echo $3
      }
      my_procedure2 "$@"
      echo "---------------withtout double quote by passing arguments---------------"
      my_procedure2 $@

      执行前用shellcheck检查会发现如下错:SC2068: Double quote array expansions to avoid re-splitting elements.命令行执行:./test_str “a b” “c d” “e f”,执行之后会发现对于函数传参,如果使用了$@(没有加双引号),会出现元素分割的情况,避免这种情况的方法就是”$@”

  3. 1
    echo -e "\033[47;31mERROR: $*\033[0m"

    用法:echo -e “\033[字背景颜色;字体颜色m字符串\033[0m” 。首先echo -e作用就是激活转义字符,因为我们要实现的是终端打印带有颜色的文字。47代表输出的文字底色是白色,31代表字体颜色是红色

    字背景颜色范围:40—-49
    40:黑
    41:深红
    42:绿
    43:黄色
    44:蓝色
    45:紫色
    46:深绿
    47:白色

    字颜色:30———–39
    30:黑
    31:红
    32:绿
    33:黄
    34:蓝色
    35:紫色
    36:深绿
    37:白色

    ========ANSI控制码的说明
    \33[0m 关闭所有属性
    \33[1m 设置高亮度
    \33[4m 下划线
    \33[5m 闪烁
    \33[7m 反显
    \33[8m 消隐
    \33[30m – \33[37m 设置前景色
    \33[40m – \33[47m 设置背景色
    \33[nA 光标上移n行
    \33[nB 光标下移n行
    \33[nC 光标右移n行
    \33[nD 光标左移n行
    \33[y;xH设置光标位置
    \33[2J 清屏
    \33[K 清除从光标到行尾的内容
    \33[s 保存光标位置
    \33[u 恢复光标位置
    \33[?25l 隐藏光标
    \33[?25h 显示光标

  4. ```bash
    declare -a var

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    declare是shell的内建命令可以用来声明shell变量、设置变量的属性,上面这段代码作用就是显式将var声明为数组变量

    `declare 选项 变量名=变量值`

    > | 选项 | 释义 | 举例 |
    > | ---- | -------------------------- | -------------------------------------------- |
    > | -i | 将变量看成整数 | declare -i A=123 |
    > | -r | 定义只读变量 | declare -r B=hello |
    > | -a | 定义普通数组;查看普通数组 | |
    > | -A | 定义关联数组;查看关联数组 | |
    > | -x | 将变量通过环境导出 | declare -x AAA=123456 等于 export AAA=123456 |

    5. shell的字符抵消原则

    ```bash
    if[x$1 = x];

    比如上面这段话里的$1就代表给.sh传的第一个参数,比如./test.sh a b,那么$1就代表了a,$2就代表了b。这样写的主要目的是当如果写成[“$1” = “$2” ] 在 $1,$2为空时会在某些bash版本中出现编译错误所以运用了shell中的字符抵消原则,实际使用过程中不管x就可以了

  5. shell里局部变量的声明

    1
    local var

    关于局部变量和全局变量:
    (1)shell 脚本中定义的变量是global的,作用域从被定义的地方开始,一直到shell结束或者被显示删除的地方为止。
    (2)shell函数定义的变量也是global的,其作用域从 函数被调用执行变量的地方 开始,到shell或结束或者显示删除为止。函数定义的变量可以是local的,其作用域局限于函数内部。但是函数的参数是local的。
    (3)如果局部变量和全局变量名字相同,那么在这个函数内部,会使用局部变量

  6. shell getopts用法

    比如:sh test.sh -u tom -p 123456

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
    while getopts "u:p:" opt; do
    case $opt in
    u)
    use=$OPTARG
    echo "user is $use" ;;
    p)
    passwd=$OPTARG
    echo "passwd is $passwd" ;;
    \?)
    echo "invalid arg" ;;
    esac
    done

    getopts的使用形式:getopts OPTION_STRING VAR;其中OPTION_STRING 就是-u和-p这些选项,$OPTARG就是tom或者123456这些自定义选项(-u,-p)后的参数

  7. shell的流程控制

    if

    • if ……fi

      1
      2
      3
      4
      5
      6
      7
      if condition
      then
      command1
      command2
      ...
      commandN
      fi
    • if …else … fi

      1
      2
      3
      4
      5
      6
      7
      8
      9
      if condition
      then
      command1
      command2
      ...
      commandN
      else
      command
      fi
    • if …elif…else…fi

      1
      2
      3
      4
      5
      6
      7
      8
      9
      if condition1
      then
      command1
      elif condition2
      then
      command2
      else
      commandN
      fi

    for循环

    1
    2
    3
    4
    5
    6
    7
    for var in item1 item2 ... itemN
    do
    command1
    command2
    ...
    commandN
    done
    1
    2
    3
    4
    5
    6
    #!/bin/bash
    arr_num=(1 2 3 4)
    for loop in ${arr_num[*]}
    do
    echo "this is a: $loop"
    done

    while语句

    while语句用来不断执行一系列命令

    1
    2
    3
    4
    while condition
    do
    command
    done

    无限循环语法格式

    1
    2
    3
    4
    while :
    do
    command
    done

    case … esac

    case … esac类似C语言里的switch case语句,可以用两个分号**;;**表示分支的结束。语法格式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    case val in
    branch1)
    command1
    command2
    ...
    commandN
    ;;
    branch2)
    command1
    command2
    ...
    commandN
    ;;
    esac

    实例如下:用户需要首先需要键入0或者1来选择编译的机型,然后再键入0或者1选择编译选项是否为Debug

    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
    14 while :
    15 do
    16 echo "----------------------------------"
    17 echo "please enter your choise(0-1):"
    18 echo "0) xxx"
    19 echo "1) yyyy"
    20 echo "----------------------------------"
    21 read input
    22 case $input in
    23 0)
    24 MACHINE_TYPE=xxx
    25 break;;
    26 1)
    27 MACHINE_TYPE=yyy
    28 break;;
    29 *) echo "please input again!!!" ;;
    30 esac
    31 done
    32
    33 while :
    34 do
    35 echo "----------------------------------"
    36 echo "please enter your choise(0-1):"
    37 echo "0) Debug"
    38 echo "1) Release"
    39 echo "----------------------------------"
    40 read input
    41 case $input in
    42 0)
    43 DEBUG_OR_RELEASE=Debug
    44 break;;
    45 1)
    46 DEBUG_OR_RELEASE=Release
    47 break;;
    48 *) echo "please input again!!!" ;;
    49 esac
    50 done
  8. shell运算符

    使用expr来进行数学运算,shell运算符包含五种运算符:

    • 算数运算符
    • 关系运算符
    • 布尔运算符
    • 字符串运算符
    • 文件测试运算符

    算数运算符

    注意点:

    • 表达式和运算符之间要有空格
    • 完整的表达式被包含在**``**反引号内
    运算符 说明 举例
    + 加法 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。

    四则运算表达式:

    表达式 举例 注意
    $(( )) echo $((1+1))
    $[ ] echo $[10-5]
    expr expr 10 / 5
    let n=1;let n+=1 等价于 let n=n+1 let sum+=$i注意这里的表达式和运算符之间不能有空格

    关系运算符

    ​ 关系运算符只支持数字,不支持字符串,除非字符串的值是数字,假定变量 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。

    布尔运算符

    shell的布尔运算符

    假定变量 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 为 “efg”:

    运算符 说明 举例
    = 检测两个字符串是否相等,相等返回 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。

    需要注意的是[],[后面必须留一个空格,]前面必须也留一个空格([]里有运算符和表达式的情况下)

    文件运算符

    操作符 说明 举例
    -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
    -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
    -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
    -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
    -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
    -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
    -p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
    -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
    -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
    -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
    -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
    -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
    -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

    -a file exists.
    -b file exists and is a block special file.
    -c file exists and is a character special file.
    -d file exists and is a directory.
    -e file exists (just the same as -a).
    -f file exists and is a regular file.
    -g file exists and has its setgid(2) bit set.
    -G file exists and has the same group ID as this process.
    -k file exists and has its sticky bit set.
    -L file exists and is a symbolic link.
    -n string length is not zero.
    -o Named option is set on.
    -O file exists and is owned by the user ID of this process.
    -p file exists and is a first in, first out (FIFO) special file or
    named pipe.
    -r file exists and is readable by the current process.
    -s file exists and has a size greater than zero.
    -S file exists and is a socket.
    -t file descriptor number fildes is open and associated with a
    terminal device.
    -u file exists and has its setuid(2) bit set.
    -w file exists and is writable by the current process.
    -x file exists and is executable by the current process.
    -z string length is zero.

    实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    echo "this is test for file attribute"

    filepath="/home/hlc/shell/test_str"
    if [ -x $filepath ]; then
    echo "the file:$filepath is excutable"
    else
    echo "no no no"
    fi
  9. printf命令

    printf输出格式:

    1
    printf  format-string  [arguments...]

    格式化字符有:

    %s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出

    printf转义序列:

    序列 说明
    \a 警告字符,通常为ASCII的BEL字符
    \b 后退
    \c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
    \f 换页(formfeed)
    \n 换行
    \r 回车(Carriage return)
    \t 水平制表符
    \v 垂直制表符
    \ 一个字面上的反斜杠字符
    \ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
    \0ddd 表示1到3位的八进制值字符

    实例:输出系统时间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
    echo "this is test for file attribute"

    filepath="/home/hlc/shell/test_str"
    if [ -x $filepath ]; then
    echo "the file:$filepath is excutable"
    else
    echo "no no no"
    fi

    #echo `date`
    #printf "the date is:%s \n" "`date`"
    printf "the date is:%s \n" "$(date)"
  10. shell函数

    shell里可以自定义函数,格式为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function  functionname ()

    {

    function body...

    return val;

    }

    注意点:

    • 其中function可有可无,**如果函数没有函数返回值,则以最后一条命令的运行结果作为返回值**,返回值的范围(0-255),如果返回值不在这个范围,使用shellcheck检查之后就会出现: SC2152: Can only return 0-255. Other data should be written to stdout
    • 函数的返回值可以在调用该函数后,通过$?来获得。
    • 调用函数时可以给其传递参数,获取函数传递的参数方法也可以用$n,详情可参见shell传递参数
    • $? 仅对其上一条指令负责,一旦函数返回后其返回值没有立即保存入参数,那么其返回值将不再能通过 $? 获得(比如连续两次echo $?,函数的返回值就被覆盖了)
    • 一定要注意:函数与命令的执行结果可以作为条件语句使用。要注意的是,和 C 语言不同,shell 语言中 0 代表 true,0 以外的值代表 false

    实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/bin/bash

    #calculate two nums's sum
    function my_func() {
    echo "argv[1]=$1"
    echo "argc[2]=$2"
    echo "come into my_func"
    read num1
    echo "the fist para is:$num1"
    read num2
    echo "the second is:$num2"
    return `expr $num1 + $num2`;
    }
    my_func 9 10
    echo "after call the func,the return val is:$?"

    遇到的坑:

    • return expr $num1 + $num2;表达式两边的反引号``写成了单引号

    • expr已经过时了,shellcheck提示:SC2003: expr is antiquated. Consider rewriting this using $((..)), ${} or [[ ]].即可使用**$((..))或者${}或者[[ ]]**来重写

    • 返回值只能0-255,因此两数之和大于255的时候就会溢出

      使用$((..))重写之后的代码如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      #!/bin/bash

      #calculate two nums's sum
      function my_func() {
      echo "argv[1]=$1"
      echo "argc[2]=$2"
      echo "come into my_func"
      read num1
      echo "the fist para is:$num1"
      read num2
      echo "the second is:$num2"
      #return `expr $num1 + $num2`;
      return $((num1 + num2))
      }
      my_func 9 10
      echo "after call the func,the return val is:$?"
  11. shell重定向

    shell通常从终端获取输入并且将输出写入到终端上,而我们可以利用重定向把输入和输出重定向到文件里

    如下的cmd表示命令、fd表示文件描述符、

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

    注意:文件描述符0通常是标准输入stdin,文件描述符1通常是标准输出stdout,文件描述符2通常是标准错误输出stderr

    实例:

    把stderr信息重定向到文件:

    1
    cmd 2>file

    把stderr信息追加到file文件

    1
    cmd 2>>file

    把stdout和stderr合并后重定向到file

    1
    cmd > file 2>&1

    执行某个命令,但不希望在屏幕上显示结果,可以把输出重定向到/dev/null,即

    1
    cmd > /dev/null

    屏蔽掉stderr和stdout

    1
    cmd > /dev/null 2>&1

    实例:

    1
    find /etc -names "*.txt" >list 2>&1

    该条命令的作用就是在/etc目录下寻找所有后缀为.txt文件,然后把输出的结果stdout重定向到list文件内。当执行到2>&1时,即表示把stderr重定向到stdout,此时的stdout已经是list了,即把上面命令的执行的错误结果重定向到list文件中,所以会发现屏幕上没有出现错误信息,查看list文件就可以看到如下信息:find: unknown predicate `-names’

  12. shell文件包含

    shell里也可以像C语言那样封装一些公共的或者通用的东西,然后供其他模块访问

    格式:

    source filepath/filename

    实例:

    test_include1.sh

    1
    2
    #!/bin/bash
    my_str="this is file1"

    test_include2.sh

    1
    2
    3
    #!/bin/bash
    source ./test_include1.sh
    echo Smy_str
  13. shell里常见的用法

    • 在脚本里获取当前脚本的绝对路径:CUR_DIR=$(cd $(dirname $0) && pwd)
  14. shell里使用”.”和”./“执行区别

    • “ ./ “ 的方式类似于新建了一个shell, 在这个新建的shell中去执行脚本中的程序,类似于新建了一个子进程,但这个子进程不继承父进程的所有非export类型的变量,并且脚本中对非export环境变量的创建或修改不会反馈到外部调用shell中
    • ” . “ 的方式类似于将脚本中的每一行指令逐条在当前shell中执行,因此它继承了当前shell的环境变量,同时脚本中对环境变量的修改也可以反馈到shell中

    测试代码:新建一个test_dot1.sh和test_dot2.sh。

    test1.sh

    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash
    VAL=10
    echo "pre val is:$VAL"

    VAL=20
    echo "middle val is:$VAL"
    echo "end"

    test2.sh

    1
    2
    3
    4
    #!/bin/bash
    echo "test the val is:$VAL"
    VAL=30
    echo "the text is:$VAL"

    首先./test1.sh,然后./test2.sh,会发现如下输出结果。不难看出如果使用./方式执行,test1.sh里变量与test2.sh的变量是互不影响的,即使在test1.sh里修改了VAL的值,test2.sh也访问不到。

    1
    2
    3
    4
    5
    6
    7
    8
    #test1.sh
    pre val is:10
    middle val is:20
    end

    #test2.sh
    test the val is:
    the text is:30

    如果我们以. test1.sh,然后. test2.sh访问,会发现如下输出结果。很显然使用.方式执行的程序的变量的修改,在另外一个sh里也能继承到

    1
    2
    3
    4
    5
    6
    7
    8
    #test1.sh
    pre val is:10
    middle val is:20
    end

    #test2.sh
    test the val is:20
    the text is:30
  15. bash里的引号

    • 双引号”” :会把引号的内容当成整体来看待,允许通过$符号引用其他变量值
    • 单引号’’ :会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
    • 反撇号`` :反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用

    实例:

    1
    2
    3
    4
    5
    6
    7
    8
    echo "$(hostname)"
    echo '$(hostname)'
    echo `date +%F`

    #输出结果
    hulc
    $(hostname)
    2018-11-22
  16. shell里的seq

    用法:比如seq 100意思就是1到100的数,默认增量为1

    Usage: seq [OPTION]… LAST
    or: seq [OPTION]… FIRST LAST
    or: seq [OPTION]… FIRST INCREMENT LAST
    Print numbers from FIRST to LAST, in steps of INCREMENT.

  17. shell里的(){}区别

    • 相同点:()和{}都是把一串的命令放在括号里面,如果命令在一行,则命令之间用;隔开
    • 不同点:
      • ()只是把一串命令重新开一个子shell进行执行,不影响当前shell环境;{}对一串命令在当前shell执行,影响当前shell环境
      • ()最后一个命令不用分号,{}最后一个命令要用分号
      • ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必要要有一个空格
      • ()和{}中括号里面的某个命令的重定向只影响改名了,但括号外的重定向则影响到括号里的所有命令