• Shell:结构化语句


    数组

    数组(Array)是若干数据的集合,其中的每一份数据都称为元素(Element)。

    Bash只支持一维数组(不支持多维数组),初始化时不需要定义数组大小,理论上可以存放无限量的数据。

    与大部分编程语言类似,数组元素的下标由0开始。

    Shell数组用括号来表示,元素用"空格"符号分割开。格式如下:

    array_name=(ele1  ele2  ele3 ... elen)
    

    Tips:赋值号=两边不能有空格,必须紧挨着数组名和数组元素。

    获取数组中的元素要使用下标[],下标可以是一个整数,也可以是一个结果为整数的表达式;当然,下标必须大于等于0。格式如下:

    ${array_name[index]}
    

    Tips:array_name是数组名,index是下标。

    Shell是弱类型的,它并不要求所有数组元素的类型必须相同,例如:

    arr=(10 24 'ddd' 'ab22' 5)
    

    获取数组所有元素

    使用@*可以获取数组中的所有元素,格式如下:

    ${array_name[*]}
    ${array_name[@]}
    

    获取数组元素个数

    使用#来获取数组元素的个数,格式如下:

    ${#array_name[@]}
    ${#array_name[*]}
    

    数组合并

    数组合并,就是将两个或两个以上的数组合并成一个个数组,格式如下:

    array_new=(${array1[@]}  ${array2[@]}...${arrayn[@]})
    array_new=(${array1[*]}  ${array2[*]}...${arrayn[*]})
    

    删除数组元素

    使用unset关键字来删除数组元素,格式如下:

    unset array_name[index]
    

    如果不写下标,则代表删除整个数组所有元素,格式如下:

    unset array_name
    

    实例

    测试ip是否ping通

    #!/usr/bin/env bash
    # Author: Rohn
    # Version: 1.0
    # Create Time: 2020/06/13
    # Test network connectivity
    
    arr_num=(3 11 25 32 200)
    for i in ${arr_num[*]}; do
      ip=192.168.110.${i}
      ping -c 1 $ip >/dev/null 2>&1
      if [ $? -eq 0 ]; then
        echo "${ip} is ok."
      else
        echo "${ip} is unreachable."
      fi
    done
    

    选择结构

    Shell中的选择结构(分支结构)有两种形式,分别是 if-elsecase-in语句,它们都根据命令的退出状态来判断条件是否成立。

    if-else语句

    基本格式

    基本结构格式:

    if condition; then
      statement(s)
    fi
    

    condition是判断条件,如果condition成立(返回True),那么then后边的语句将会被执行;如果 condition不成立(返回False),那么不会执行任何语句。

    Tips:最后必须以fi来闭合,fi就是if 倒过来拼写。

    if-else

    如果有两个分支,就可以使用if-else语句,格式:

    if condition; then
      statement1
    else
      statement2
    fi
    

    如果condition成立,那么then后边的 statement1语句将会被执行;否则,执行else 后边的statement2语句。

    if-elif-else

    当分支比较多时,可以使用if-elif-else 结构,格式:

    if condition1; then
      statement1
    elif condition2;then
      statement2
    ...
    else
      statementn
    fi
    

    Tips:ifelif后边都得跟着then

    语句的执行逻辑:

    • 如果condition1成立,那么执行statement1,如果不成立,则执行elif语句;
    • 如果elif语句不成立,则执行else语句;

    case-in语句

    当分支较多,且判断条件比较简单时,推荐使用case-in语句。格式如下:

    case expression in
      pattern1)
        statement1
        ;;
      pattern2)
        statement2
        ;;
      ...
      *)
        statementn
    esac
    
    • expression表示表达式,既可以是一个变量、一个数字、一个字符串,还可以是一个数学计算表达式,或者是命令的执行结果,只要能够得到expression的值就可以。
    • pattern表示匹配模式,可以是一个数字、一个字符串,甚至是一个简单的正则表达式。

    case会将expression的值与 pattern1pattern2...patternn逐个进行匹配:

    • 如果expression和某个模式(比如 pattern2)匹配成功,就会执行这模式(比如 pattern2)后面对应的所有语句(该语句可以有一条,也可以有多条),直到遇见双分号;;才停止;然后整个case-in语句就执行完了,程序会跳出整个 case-in语句,执行esac后面的其它语句。
    • 如果 expression 没有匹配到任何一个模式,那么就执行*)后面的语句(*表示其它所有值),直到遇见双分号;;或者esac才结束。*)相当于多个if分支语句中最后的else部分。

    Tips:分支*)并不是什么语法规定,它只是一个正则表达式,*表示任意字符串,所以不管expression的值是什么,*)总能匹配成功。因此,可以没有*)部分,如果expression没有匹配到任何一个模式,那么就不执行任何操作。

    除最后一个分支外(这个分支可以是普通分支,也可以是*)分支),其它的每个分支都必须以;;结尾,;;代表一个分支的结束,不写的话会有语法错误。最后一个分支可以写;;,也可以不写,因为无论如何,执行到esac都会结束整个case-in语句。

    case-inpattern部分支持简单的正则表达式,具体来说,可以使用以下几种格式:

    格式 说明
    * 表示任意字符串。
    [abc] 表示 a、b、c 三个字符中的任意一个。比如,[15ZH] 表示 1、5、Z、H 四个字符中的任意一个。
    [m-n] 表示从 m 到 n 的任意一个字符。比如,[0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。
    | 表示多重选择,类似逻辑运算中的或运算。比如,abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。

    ;;&终止每个条件块,例如:

    read -n 1 -p "Type a character > "
    echo
    case $REPLY in
      [[:upper:]])    echo "'$REPLY' is upper case." ;;&
      [[:lower:]])    echo "'$REPLY' is lower case." ;;&
      [[:alpha:]])    echo "'$REPLY' is alphabetic." ;;&
      [[:digit:]])    echo "'$REPLY' is a digit." ;;&
      [[:graph:]])    echo "'$REPLY' is a visible character." ;;&
      [[:punct:]])    echo "'$REPLY' is a punctuation symbol." ;;&
      [[:space:]])    echo "'$REPLY' is a whitespace character." ;;&
      [[:xdigit:]])   echo "'$REPLY' is a hexadecimal digit." ;;&
    esac
    

    输出结果如下:

    Type a character > a
    'a' is lower case.
    'a' is alphabetic.
    'a' is a visible character.
    'a' is a hexadecimal digit.
    

    循环结构

    循环结构语句大致分为4种:

    • while
    • until
    • for
    • select

    while语句

    当条件满足时,while重复地执行一组语句,当条件不满足时,就退出while循环。格式如下:

    while condition; do
      statements
    done
    

    执行流程如下:

    • 先对condition进行判断,如果该条件成立,就进入循环,执while循环体中的语句,也就是dodone之间的语句。这样就完成了一次循环。
    • 每一次执行到done的时候都会重新判断condition是否成立,如果成立,就进入下一次循环,继续执行dodone之间的语句,如果不成立,就结束整个while循环,执行done后面的其它Shell代码。
    • 如果一开始condition就不成立,那么程序就不会进入循环体。

    死循环

    格式一:

    while true; do
      statements
    done
    

    格式二:

    while [ 1 ]; do
      statements
    done
    

    until语句

    until循环当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环。

    until condition; do
      statements
    done
    

    until循环的执行流程为:

    • 先对condition进行判断,如果该条件不成立,就进入循环,执行until循环体中的语句(dodone之间的语句),这样就完成了一次循环。
    • 每一次执行到done的时候都会重新判断condition是否成立,如果不成立,就进入下一次循环,继续执行循环体中的语句,如果成立,就结束整个 until循环,执行done后面的其它Shell代码。

    for语句

    C语言风格的 for 循环

    格式如下:

    for((exp1; exp2; exp3)); do
      statements
    done
    

    exp1exp2exp3是三个表达式,其中exp2是判断条件,for循环根据exp2的结果来决定是否继续下一次循环;

    它的运行过程为:

    1. 先执行exp1
    2. 再执行exp2,如果它的判断结果是成立的,则执行循环体中的语句,否则结束整个for循环。
    3. 执行完循环体后再执行exp3
    4. 重复执行2、3步骤,直到exp2的判断结果不成立,就结束循环。

    for-in循环

    格式如下:

    for variable in value_list; do
      statements
    done
    

    variable表示变量,value_list表示取值列表。

    每次循环都会从value_list中取出一个值赋给变量 variable,然后进入循环体(dodone之间的部分),执行循环体中的statements。直到取完value_list中的所有值,循环就结束了。

    value_list

    • 具体的值,例如:
    for i in 1 2 3 'dd';do echo $i;done
    
    • {start..end},例如:
    # 求1到10的和
    sum=0
    for i in {1..10}; do
      sum=$((sum+i))
    done
    echo $sum
    
    • 命令的执行结果,例如:
    # 求100以内偶数的和
    for i in $(seq 2 2 100); do
      sum=$((sum+i))
    done
    echo $sum
    
    • 通配符,例如:
    # 打印当前路径.log结尾的文件
    for i in *.log; do echo $i;done
    

    Tips:若当前路径无.log结尾的文件,则会打印*.log

    • 特殊变量,$*$@等,例如:
    for i in $@; do
      sum=$((sum+i))
    done
    echo $sum
    

    select-in语句

    select-in循环用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能,非常适合终端(Terminal)这样的交互场景。格式如下:

    select variable in value_list; do
      statements
    done
    

    variable表示变量,value_list表示取值列表。

    例如:

    echo "选择你要学习的科目:"
    select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
      echo "你选择了${i}。"
    done
    

    结果如下:

    选择你要学习的科目:
    1) Linux
    2) Python
    3) Java
    4) C++
    5) PHP
    #? 5
    你选择了PHP。
    #? 2
    你选择了Python。
    #? 666
    你选择了。
    

    Tips:select是死循环,输入空值或者输入的值无效,都不会结束循环,只有遇到break语句,或者按下Ctrl+D组合键才能结束循环。

    例如:

    echo "选择你要学习的科目:"
    select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
      echo "你选择了${i}。"
      break
    done
    

    结果如下:

    选择你要学习的科目:
    1) Linux
    2) Python
    3) Java
    4) C++
    5) PHP
    #? 5
    你选择了PHP。
    

    select-in语句常和case-in语句一起使用。

    break

    格式如下:

    break n
    

    n表示跳出循环的层数,如果省略n,则表示跳出当前。

    continue

    格式如下:

    continue n
    

    n表示循环的层数:

    • 如果省略n,则表示continue只对当前层次的循环语句有效,遇到continue会跳过本次循环,忽略本次循环的剩余代码,直接进入下一次循环。
    • 如果带上n,比如n的值为2,那么continue 对内层和外层循环语句都有效,不但内层会跳过本次循环,外层也会跳过本次循环,其效果相当于内层循环和外层循环同时执行了不带ncontinue

    break的区别:

    • break用来结束当前整个循环;
    • continue用来结束本次循环,直接跳到下一次循环,如果循环条件成立,还会继续循环;

    函数

    函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。

    函数定义

    格式如下:

    function func_name() {
        statements
        [return value]
    }
    

    Tips:关键词function是可选的,但必须在一个项目中保持一致。

    说明:

    • function是Shell中的关键字,专门用来定义函数,可以不写,但要求在整个项目脚本中保持一致,即统一不写或都写;
    • func_name是函数名,按照约定规范,函数名后面必须带上()
    • statements是函数要执行的代码,也就是一组语句;
    • return value表示函数的返回值,其中return 是Shell关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。

    函数调用

    调用Shell函数时可以给它传递参数,也可以不传递。如果不传递参数,直接给出函数名字即可,格式如下:

    func_name
    

    如果传递参数,那么多个参数之间以空格分隔:

    func_name param1 param2 param3...
    

    Tips:不管是哪种调用方式,函数名字后面都不需要带()

    函数参数

    函数参数是Shell位置参数的一种,在函数内部可以使用$n来接收,例如,$1表示第一个参数,$2表示第二个参数,依次类推。

    除了$n,还有另外三个比较重要的变量:

    • $#可以获取传递的参数的个数;
    • $@或者$*可以一次性获取所有的参数
  • 相关阅读:
    centos7安装rabbitmq 总结
    python第六十三天-- 第十一周作业
    python第六十一天,第六十二天 redis
    python第六十天-----RabbitMQ
    python第五十四天--第十周作业
    python第五十三天--进程,协程.select.异步I/O...
    python第五十二天---第九周作业 类 Fabric 主机管理程序
    python第五十一天----线程,Event,队列
    Python基础之-面向对象编程(引言)
    Python中的模块
  • 原文地址:https://www.cnblogs.com/Rohn/p/13234419.html
Copyright © 2020-2023  润新知