ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Shell:结构化语句

2020-07-04 12:02:25  阅读:229  来源: 互联网

标签:语句 do 结构化 Shell echo 循环 done 数组


目录

数组

数组(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,还有另外三个比较重要的变量:

  • $#可以获取传递的参数的个数;
  • $@或者$*可以一次性获取所有的参数

标签:语句,do,结构化,Shell,echo,循环,done,数组
来源: https://www.cnblogs.com/Rohn/p/13234419.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有