Shell脚本学习

记录常用的Shell脚本语法

变量

  • 赋值

    1
    2
    3
    # 赋值
    a=1
    b=2
  • 计算

    1
    2
    # 计算(用$((语句))的形式)
    c=$((a+b)) # 等于a+b
  • 字符串操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 字符串操作
    str="blog.yumc.pw"
    # 字符串长度
    echo ${#str} # => 12
    # 从某个位置开始截取字符串
    echo ${str:5} # => yumc.pw
    # 从某个位置开始截取指定几个字符串
    echo ${str:5:4} # => yumc
    # 从开头位置开始删除字符到某个位置
    echo ${str#blog.} # => yumc.pw
    echo ${str#*.} # => yumc.pw 从开头删除最短匹配串
    echo ${str##*.} # => pw 从开头删除最长匹配串
    # 从结尾某个位置开始删除到某个字符
    echo ${str%.pw} # => blog.yumc
    echo ${str%.*} # => blog.yumc 从结尾删除最短匹配串
    echo ${str%%.*} # => blog 从结尾删除最长匹配串
  • 数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 数组初始化
    fruits=('apple' 'orange' 'banana')
    # 设置某个元素
    fruits[0]=bigapple
    # 数组长度
    echo ${#fruits[@]} # => 3
    # 取得数组指定内容
    echo ${fruits[0]} # => bigapple
    # 取得所有内容 ${fruits[*|@]}
    echo ${fruits[@]} # => bigapple orange banana
    echo ${fruits[*]} # => bigapple orange banana
    echo ${fruits[*]:0} # => bigapple orange banana
    # 删除整个数组
    unset fruits
    # 删除某个元素
    unset fruits[0]
    # 数组的截取
    echo ${fruits[*]:1} # => orange banana 开始的Index
    # ${array[*]:start:size} start: 开始的Index size: 截取的长度
    echo ${fruits[*]:1:1} # => orange
    echo ${fruits[*]:1:2} # => orange banana

判断操作

操作符详见 Shell脚本内的操作符解释

  • test 操作

    1
    test -操作符 参数
  • () 操作

    • 命令组: 括号中的命令会展开一个子Shell顺序执行, 括号中的变量不能被后续脚本使用,括号中的多个命令用;隔开,最后一个命令可以没有分号,各个命令和括号之间不必有空格
    • 命令替换: 等同于执行 命令, Shell会扫描命令行,当发现$(命令)的结构时,会先执行内部的命令,得到标准输出,再将该值输出到原有的命令
    • 初始化数组: array=(a b c d)
  • (()) 操作
    • 整数扩展
  • [] 操作 注意 用[]的情况下 括号左边右边都要有空格
    1
    [ -操作符 参数 ]

条件分支语句

  • IF 条件判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    if [ 表达式 ]; then
    方法块
    fi

    if [ 表达式 ]; then
    方法块
    else
    方法块
    fi

    if [ 表达式 ]; then
    方法块
    elif [ 表达式 ]; then
    方法块
    else
    方法块
    fi
  • CASE 多条件判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    case 变量 in
    值1)
    方法块
    ;;
    值2)
    方法块
    ;;
    值3)
    方法块
    ;;
    esac

循环语句

  • FOR 循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    for ((i=1; i<=100; i ++)); do  
    echo $i
    done
    for i in {1..100}; do
    echo $i
    done
    # 序列化生成1-100
    for i in `seq 1 100`; do
    echo $i
    done
    fruits='apple orange banana'
    for i in ${fruits}; do
    echo $i
    done
    fruits=(apple orange banana)
    for i in ${fruits[*]}; do
    echo $i
    done
    # 压缩目录下所有的文件
    for file in ./*; do
    if test -d $file; then
    tar -cvzf $file.tar.gz $file
    fi
    done
  • WHILE 循环(表达式为真则执行)

    1
    2
    3
    while 表达式; do
    循环快
    done
  • UNTIL 循环(表达式为假则执行)

    1
    2
    3
    until 表达式; do
    循环快
    done

函数(待填坑)

  • 异常退出

    1
    2
    set -e # 遇到任何命令返回值非0 则退出
    set +e # 关闭检测
  • 管道命令异常退出(set -e 只能检测单条命令)

    1
    set -e pipefail
  • 读取脚本参数

    1
    2
    3
    4
    5
    $# => 当前脚本传入参数个数
    $? => 上一个命令执行结果
    $1-9 => 对应 1-9 个脚本参数
    $* => 传递的所有参数 多合一 1 2 3 => "$*" => "1 2 3"
    $@ => 传递的所有参数 分离 1 2 3 => "$@" => "1" "2" "3"
  • 循环读取脚本参数(参数个数大于10个的时候很有用 shift 是把参数往前移动)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    while [ $# -gt 0 ]; do
    case "$1" in
    --mirror)
    mirror="$2"
    shift
    ;;
    --dry-run)
    DRY_RUN=1
    ;;
    --*)
    echo "Illegal option $1"
    ;;
    esac
    shift $(( $# > 0 ? 1 : 0 ))
    done