zoukankan      html  css  js  c++  java
  • 入门 shell 从脚本开始


    编写脚本实现在指定文件路径下查找文件夹或文件名。
     
    脚本如下:
    #!/bin/sh
    # lazy find
     
    # GNU All-Permissive License
    # Copying and distribution of this file, with or without modification,
    # are permitted in any medium without royalty provided the copyright
    # notice and this notice are preserved.  This file is offered as-is,
    # without any warranty.
     
    ## help function
     
    function helpu {
        echo " "
        echo "Fuzzy search for filename."
        echo "$0 [--match-case|--path] filename"
        echo " "
        exit
    }
     
    ## set variables
     
    MATCH="-iname"
    SEARCH="."
     
    ## parse options
     
    while [ True ]; do
    if [ "$1" = "--help" -o "$1" = "-h" ]; then
        helpu
    elif [ "$1" = "--match-case" -o "$1" = "-m" ]; then
        MATCH="-name"
        shift 1
    elif [ "$1" = "--path" -o "$1" = "-p" ]; then
        SEARCH="${2}"
        shift 2
    else
        break
    fi
    done
     
    ## sanitize input filenames
    ## create array, retain spaces
     
    ARG=( "${@}" )
    set -e
     
    ## catch obvious input error
     
    if [ "X$ARG" = "X" ]; then
        helpu
    fi
     
    ## perform search
     
    for query in ${ARG[*]}; do
        /usr/bin/find "${SEARCH}" "${MATCH}" "*${ARG}*"
    done
    该脚本来自网络,非常简洁,优雅。
     
    通过该脚本来学习 shell,脚本中包括如下几个 shell 知识点:
    • Shebang 行
    • 变量
    • 循环
    • 列表
    • 参数
    • 函数
    • 判断
    • set
    ## Shebang 行
    Shebang 行是脚本的第一句,通常记为 #!/bin/bash 这种形式,指定执行该脚本需要用到的解释器。如果不加,在执行脚本的时候可通过命令 /bin/bash 指定。
     
    ## 变量
    变量在 shell 中写作 variable=value 的形式(等号两边不能有空格!),variable 为变量名,value 为变量的值。
     
    变量名需遵守以下命名规则:
    • 由字母,数字,下划线组成。
    • 变量名开头不能是数字,可以是字母或下划线。
    • 变量名中不允许出现空格和标点符号。
     
    shell 将所有 value 看作字符串,如果 value 有空格,则需使用引号将 value 括起来。
     
    常用的几种变量写法:
    MATCH="-iname"
    MATCH=-iname
     
    NAME="lian hua"
     
    可通过在变量名前加美元符 $ 或加大括号 ${variable} 的形式引用变量:
    echo $MATCH
     
    echo ${MATCH}
     
    注意,bash 读取不存在的变量,不会报错,会打印出空字符,如下:
    [lianhuasheng@demo home]$ echo $lianhua
     
    [lianhuasheng@demo home]$ 
     
    在脚本执行的时候,如果变量不存在一般会期望脚本报错,这时候 set 命令就派上用场了。
     
    ## set
    set 可用来设置子 shell 的运行环境,不加任何参数的 set 会 show 出当前 shell 的自带环境变量和自定义环境变量等。另一方面,set 也可用来编写更安全的 shell 脚本。
     
    set -e 命令可使得在其后执行的命令,如果失败了即报错,后续的命令将不被执行。如果期望命令执行失败后,后续命令还能继续执行,可打开 set +e 选项:
    set -e
     
    command1
    command2
     
    set +e
     
    set -u 可使得bash 在读取不存在变量的时候报错。
     
    ## 循环
    在上例中使用到了 while 和 for 循环:
     
    while 循环的语法格式如下:
    while condition; do
        commands
    done
     
    for 循环的语法格式有三种,分别是:
    ## 1. normal for script
    for variable in list; do
        commands
    done
     
    ## demo for script 
    #!/bin/bash
     
    for i in lian hua sheng; do
      echo $i
    done
     
    ## 2. c style for script
    for (( expression1; expression2; expression3 )); do
      commands
    done
    其中,c 语言风格的 for 循环中,expression1 用来设置循环初始值,expression2 用来设置循环结束条件,expression3 用来更新值。
     
    ## 列表
    上小节看到 for 循环中的循环体是 list 列表,列表可通过大括号扩展或者参数传递等的形式取得。
     
    # 大括号扩展
    使用大括号扩展 {start..end} 形式扩展值为列表:
    [lianhuasheng@demo home]$ echo {1..10}
    1 2 3 4 5 6 7 8 9 10
     
    将扩展出的列表运用于 for 循环中:
    [lianhuasheng@demo home]$ echo {1..10}
    1 2 3 4 5 6 7 8 9 10
    注意,默认 echo 输出的文本文件后加 换行符,所以这里指定 echo 的 -n 选项取消换行符。
     
    # 参数传递
    除了大括号扩展,还有一种常见的组成列表的形式是参数传递。参数传递,即在执行脚本时指定的参数,shell 脚本中分别使用如下几种符号表明参数:
    • $0: 脚本文件名。
    • $1 - $9: 脚本的第 1 个参数到第 9 个参数,超过 9 个参数使用 ${10}, ${11}... 形式表示。
    • $#: 传入脚本的参数数量。
    • $@: 传入脚本中的全部参数,它是一个列表。
    [lianhuasheng@demo home]$ cat parameter.sh
    #!/bin/bash
    # script.sh
     
    echo "all parameters:" $@
    echo "number of parameters:" $#
    echo '$0 = ' $0
    echo '$1 = ' $1
    echo '$2 = ' $2
    echo '$3 = ' $3
     
    [lianhuasheng@demo home]$ ./parameter.sh lian hua
    all parameters: lian hua
    number of parameters: 2
    $0 =  ./parameter.sh
    $1 =  lian
    $2 =  hua
    $3 =                            # $3 没有读取参数,并没有报错
     
    在 for 循环中常用 $@ 作为循环体:
    for value in "$@"; do
        echo ${value}
    done
     
    ## 数组
    for 循环中还可将数组作为循环体,在上例脚本中看到这样一条语句 ARG=("$@"),其中圆括号 () 即是将字符串转为数组的符号。
     
    # 创建数组
    创建数组有多种方式:直接赋值,间接赋值,外部赋值等方式:
     
    1. 直接赋值:
    [lianhuasheng@demo home]$ arg=(lian hua sheng)
    [lianhuasheng@demo home]$ echo ${arg[@]}
    lian hua sheng
     
    2. 间接赋值:
    [lianhuasheng@demo home]$ arg[0]=da
    [lianhuasheng@demo home]$ arg[1]=shuai
    [lianhuasheng@demo home]$ arg[2]=ge
    [lianhuasheng@demo home]$ echo ${arg[@]}
    da shuai ge
     
    3. 外部赋值:
    [lianhuasheng@demo home]$ read -a arg
    hei hei hei
    [lianhuasheng@demo home]$ echo ${arg[@]}
    hei hei hei
     
    外部赋值通过使用 read 命令,将用户的输入读入到数组 arg 中。
     
    # 读取数组
    通用的读取数组中的元素有两种方式:读取单个元素和读取所有元素:
     
    1. ${arg[index]} 读取单个元素:
    [lianhuasheng@demo home]$ echo ${arg[@]}
    da shuai ge
    [lianhuasheng@demo home]$ echo ${arg[1]}
    shuai
     
    2. 读取所有元素:
    [lianhuasheng@demo home]$ echo ${arg[@]}
    da shuai ge
     
    [lianhuasheng@demo home]$ echo ${arg[*]}
    da shuai ge
     
    通过 ${array[@]} 和 ${array[*]} 都可读取数组的所有元素,$array[*] 相当于不加双引号的 $array[@],加不加双引号的区别可看下例:
    [lianhuasheng@demo home]$ arg=(lian "hua sheng" da "shuai-ge")
     
    [lianhuasheng@demo home]$ for value in ${arg[*]}; do echo "parameter: " ${value}; done
    parameter:  lian
    parameter:  hua
    parameter:  sheng
    parameter:  da
    parameter:  shuai-ge
     
    [lianhuasheng@demo home]$ for value in "${arg[*]}"; do echo "parameter: " ${value}; done
    parameter:  lian hua sheng da shuai-ge
     
    [lianhuasheng@demo home]$ for value in ${arg[@]}; do echo "parameter: " ${value}; done
    parameter:  lian
    parameter:  hua
    parameter:  sheng
    parameter:  da
    parameter:  shuai-ge
     
    [lianhuasheng@demo home]$ for value in "${arg[@]}"; do echo "parameter: " ${value}; done
    parameter:  lian
    parameter:  hua sheng
    parameter:  da
    parameter:  shuai-ge
     
    从示例中可以看出,当 $array[@] 加上双引号之后可正确输出数组 arg 中的元素,不加双引号的 $array[@] 和 $array[*] 的结果一致,加了双引号的 $array[*] 会将数组中所有元素作为单个字符串返回。
     
    注意,不加索引读取数组元素读到的是第一个数组元素:
    [lianhuasheng@demo home]$ echo $arg
    lian
    [lianhuasheng@demo home]$ echo ${arg}
    lian
    [lianhuasheng@demo home]$ echo $arg[0]
    lian[0]
    [lianhuasheng@demo home]$ echo ${arg}[0]
    lian[0]
     
    通过 $arg 和 ${arg} 两种方式读取数组第一个元素,通常两种方式读取变量的结果是一致的,不过推荐使用 ${ } 这种方式读取变量,它可以精确界定变量名称的范围。
    如果读取变量时不用大括号,则 bash 会解析 $arg, 然后将 [0] 原样输出。
     
    ## 条件判断
    条件判断是使用 if..elif..fi 根据指定条件判断命令执不执行的判断语句,它的语法如下:
    if conditions; then
        commands
    elif conditions; then
        commands
    else
        commands
    fi
     
    其中,elif 和 else 是可选的。
     
    条件判断有多种判断表达式,如下:
    • 文件判断
    • 字符串判断
    • 整数判断
    • 正则判断
    • test 判断逻辑运算
    • 算术判断
    • 普通命令的逻辑运算
     
    这里,脚本中的判断表达式皆属于字符串判断,其判断表达式为:
    • [ string ]:string 不为空,则判断为真。
    • [ string1 = string2 ]:string1 和 string2 字符串相同则判断为真,同 [ string1 == string2 ]。
    • [ string1 != string2 ]:string1 和 string2 不同则判断为真。
    • [ -n string ]:string 长度大于 0 则判断为真。
    • [ -z string ]:string 长度等于 0 则判断为真。
     
    注意,这里判断表达式也使用到了 test 命令,test 有三种形式,分别是:
    # 1 style of test
    test expression
     
    # 2 style of test
    [ expression ]
     
    # 3 style of test
    [[ expression ]]
     
    所以,[ -n string ] 判断表达式又可写成 test -n string 这种形式。
     
    关于其它判断表达式的使用可看这里
     
    ## 函数
    shell 中有两种函数写法:
    # 1 style of function
    function fn {
        commands
    }
     
    # 2 style of function
    fn() {
        commands
    }
     
    介绍函数主要从以下几个角度入手:函数参数,函数返回值和函数变量:
     
    # 函数参数
    通常执行脚本传递的参数即可作为函数的参数,但是函数也支持自定义传参:
    #!/bin/bash
     
    function input_param {
        echo "I am input function, the input parameters are: "
        echo "$@"
    }
     
    function input_defined_param {
        echo "I am input defined function, the defined parameters are: "
        echo "The first parameter is: " "${1}"
        echo "The second parameter is: " "${2}"
        echo "The totally parameters are: " "${@}"
    }
     
    input_param ${@}
    input_defined_param lian hua
     
    和脚本中参数类似,函数中也可使用 ${1}/${@}/$#/$* 等参数符号。但是,函数使用特殊参数环境作为自己的参数值,它无法直接获取脚本在命令行中的参数值。因此,需要传递参数给函数。
     
    # 函数返回值
    函数中可使用 return 返回函数执行结果,在调用函数之后可使用 $? 查看函数返回结果:
    [lianhuasheng@demo home]$ ./function_return.sh
    127
    [lianhuasheng@demo home]$ cat function_return.sh
    #!/bin/bash
     
    function_return() {
        return 127
    }
     
    function_return
    echo $?
     
    其中,$? 是 bash 提供的特殊变量,它是上一条命令的退出码,如果 $? 为 0 则表示命令执行成功,非零表示执行失败:
    [lianhuasheng@demo home]$ cd lianhua
    -bash: cd: lianhua: No such file or directory
    [lianhuasheng@demo home]$ echo $?
    1
     
    [lianhuasheng@demo home]$ cd query/
    [lianhuasheng@demo query]$ echo $?
    0
     
    除了 return 返回函数结果之外,在函数或者脚本中也可使用 exit 返回退出码,bash 会读取返回的退出码,并且脚本 exit 之后的语句不会被执行。
    [lianhuasheng@demo home]$ cat function_exit.sh
    #!/bin/bash
     
    function_exit() {
        exit 127
    }
     
    function_exit
    echo "kissMe"
    [lianhuasheng@demo home]$ ./function_exit.sh       # echo "kissMe" 没有执行到
    [lianhuasheng@demo home]$ echo $?
    127
    [lianhuasheng@demo home]$ vi function_exit.sh
    [lianhuasheng@demo home]$ ./function_exit.sh
    [lianhuasheng@demo home]$ echo $?
    0
     
    # 函数变量
    函数中声明的变量都是全局变量,可使用 local 将变量转为局部变量:
    [root@demo bash]# cat function_variable.sh
    #!/bin/bash
     
    name="lian hua"
     
    function rename {
        echo "My original name is: " "${name}"
        name="${1}"
        echo "Now, My name is: " "${name}"
    }
     
    function naming {
        initName="lao wang"
    }
     
    naming
    echo ${initName}                   # 函数外可以使用函数内定义的变量
     
    rename "shuai ge"
    echo "once again, my name is: " "${name}"          # 函数内可以修改函数外定义的全局变量
     
    [root@demo bash]# ./function_variable.sh
    lao wang
    My original name is:  lian hua
    Now, My name is:  shuai ge
    once again, my name is:  shuai ge
     
    [root@demo bash]# cat function_variable.sh
    #!/bin/bash
    function naming {
        firstName="wang"
        local lastName="lao"
    }
     
    naming
    echo ${firstName}
     
    set -eux
    echo ${lastName}
    set +eux
     
    [root@demo bash]# ./function_variable.sh
    wang
    ./function_variable.sh: line 12: lastName: unbound variable         # lastName 是局部变量,无法引用
     
     
  • 相关阅读:
    WCF Server Console
    Restart IIS With Powershell
    RestartService (recursively)
    Copy Files
    Stopping and Starting Dependent Services
    多线程同步控制 ManualResetEvent AutoResetEvent MSDN
    DTD 简介
    Using Powershell to Copy Files to Remote Computers
    Starting and Stopping Services (IIS 6.0)
    java中的NAN和INFINITY
  • 原文地址:https://www.cnblogs.com/xingzheanan/p/13461250.html
Copyright © 2011-2022 走看看