Shell:结构化语句

数组

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

Bash只支持一维数组(不支持多维数组),初始化时不须要定义数组大小,理论上能够存放无限量的数据。正则表达式

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

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

array_name=(ele1  ele2  ele3 ... elen)

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

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

${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] 表示 一、五、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. 重复执行二、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,还有另外三个比较重要的变量:

  • $#能够获取传递的参数的个数;
  • $@或者$*能够一次性获取全部的参数
相关文章
相关标签/搜索