Linux基础之bash脚本进阶篇-循环语句(for,while,until)及其特殊用法

什么是循环语句、死循环?

循环语句:将一段代码重复执行0、1或多次;它有进入条件与退出条件。

重复运行多少次?我们如何设定循环语句的重复次数?

为了设定循环语句的重复次数于是就有了进入条件与退出条件。

进入条件:条件满足时进入循环。

退出条件:不符合条件退出循环。

一种特殊的循环:死循环

死循环:在编程中,一个无法靠自身的控制终止的循环称为"死循环"。死循环的出现有两种情况:

1、因程序需要刻意写的;2、因程序员的失误造成的。

第二种的死循环通常会造成比较严重的程序错误,甚至会因此而影响物理机。因此死循环的使用需要合理的设计

实验环境CentOS7.2



本文重要的三个循环语句:for、while、until

………………………………………………………………………………………………………………………

for循环

for语句的使用格式:

for NAME in LIST(列表); do

循环体

done

列表生成方式

(1) 整数列表

    {start..end}

    $(seq start [[step]end])

(2) glob

    /etc/rc.d/rc3.d/K*

(3) 命令

………………………………………………………………………………………………………………………

下面以一个例子看看for的具体作用

示例:计算1+2+...+10的值

#!/bin/bash
#sum the value of "1+2+...+10"
#author chawan 
#date:20160906
declare -i sum=0
for x in {1..10};do
   let sum+=$x
done
echo "The sum is : $sum"

运行脚本0906-1结果如下

[[email protected] hmworks]# sh 0906-1
The sum is : 55

上面使用了第一种的整数列表中的第一种形式,这里如果是“1+2+...+n”这种形式那么{start..end}就不再适用,此时就只能使用$(seq start [[step]end])。下面再举一个例子说明

示例:计算“1+2+...+n”的值

#!/bin/bash
#sum “1+2+...+n”
#author chawan
#date:20160906
declare -i sum=0
#以交互的方式输入一个正整数
read -p "Please inset a number :" num
#判断输入的数是否为空,为空则提示并退出
[ -z $num ] && echo "Please input a number!" && exit 1
#判断输入的是否是正整数,若是则执行循环,若不是提示输入正整数并退出
if [[ $num =~ ^[1-9][0-9]{0,}$ ]] ; then
   for i in {1..$num};do   
#for i in `seq 1 $num`;do
       let sum+=$i
       #sum=$[$sum+$i] 这种方式也可以不过不够简练
   done
else
  echo "Error : please input a positive integer" && exit 2
fi
#显示最后的和
echo "The sum is : $sum"

下面执行该脚本

[[email protected] hmworks]# sh 0906-2
Please inset a number :8
0906-2:行14: let: sum+={1..8}: 语法错误: 期待操作数 (错误符号是 "{1..8}")
The sum is : 0

该结果说明{start..end}形式不适用于有变量出现的情况,既然这个不行就来试试$(seq start [[step]end])

#!/bin/bash
#sum “1+2+...+n”
#author chawan
#date:20160906
declare -i sum=0
#以交互的方式输入一个正整数
read -p "Please inset a number :" num
#判断输入的数是否为空,为空则提示并退出
[ -z $num ] && echo "Please input a number!" && exit 1
#判断输入的是否是正整数,若是则执行循环,若不是提示输入正整数并退出
if [[ $num =~ ^[1-9][0-9]{0,}$ ]] ; then
   for i in `seq 1 $num`;do
       let sum+=$i
       #sum=$[$sum+$i]
   done
else
  echo "Error : please input a positive integer" && exit 2
fi
#显示最后的和
echo "The sum is : $sum"

执行该脚本

[[email protected] hmworks]# sh 0906-2
Please inset a number :10
The sum is : 55
[[email protected] hmworks]# sh 0906-2
Please inset a number :100
The sum is : 5050

该结果表明$(seq start [[step]end])适用性更好,因此一般建议使用它。

列表的glob与命令这两种就不再具体演示。大家感兴趣可以自己尝试下做个实验体会体会。

………………………………………………………………………………………………………………………

while循环

while语句使用格式:

while CONDITION; do

循环体

done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环;

因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正;

进入条件:CONDITION为true;

退出条件:CONDITION为false

………………………………………………………………………………………………………………………

示例:计算1+2+...+10的值

#!/bin/bash
#sum the value of "1+2+...+10"  while
#author chawan
#date:20160906
#为了严谨起见,事先声明变量sum及i为整数型
declare -i sum=0
declare -i i=1
while [ $i -le 10 ];do
    let sum+=$i    #sum=$[$sum+$i]的简写形式
    let i++        #不断修正变量体
done
echo "The sum is : $sum"

执行脚本,查看其是否正确执行

[[email protected] hmworks]# sh 0906-3
The sum is : 55

while与for的不同在于

1、不需要列表,因此可以大大节省内存空间,因为for如果列表很大会占用较多内容空间,对系统性能会造成影响,所以此时while的优越性就显现出来,它不需要占用很多内存空间,只需要两个变量的空间及做加法即可。

2、while需要修正体来不断修正变量,最终在符合退出条件时结束循环

………………………………………………………………………………………………………………………

until循环

until语句使用格式:

until CONDITION; do

循环体

done

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“false”,则执行一次循环;直到条件测试状态为“true”终止循环;

因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正;

进入条件:CONDITION为false;

退出条件:CONDITION为true

until的用法同while,唯一的区别在于进入循环与退出循环的条件相反

以相同的例子来体会二者的区别

………………………………………………………………………………………………………………………

示例:计算1+2+...+10的值

#!/bin/bash
#sum the value of "1+2+...+10"  until
#author chawan
#date:20160906
declare -i sum=0
declare -i i=1
until [ $i -gt 10 ];do
    let sum+=$i
    let i++
done
echo "The sum is : $sum"

执行脚本,查看结果是否正确输出

[[email protected] hmworks]# sh 0906-4
The sum is : 55

通过比较while与until的唯一差别就在于判断条件。这两者其实算是同一种循环语句,只是进入及退出循环的条件正好相反。



循环控制语句(用于循环体中)

1、continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;

其使用格式

    while CONDTIITON1; do

      CMD1

...

      if CONDITION2; then

       continue

      fi

      CMDn

...

    done

………………………………………………………………………………………………………………………

示例:求100以内所有偶数之和;要求循环遍历100以内的所正整数

#!/bin/bash
#求100以内所有偶数之和;要求循环遍历100以内的所正整数
#author chawan
#date:20160906
declare -i i=1
declare -i sum=0
while [ $i -le 100 ];do
    let i++
#如果为奇数则跳过该循环
    if [ $[${i}%2] -eq 1 ];then
      continue
    fi
    let sum+=$i
done
echo  "The even number sum : $sum"

执行脚本,查看结果是否正确显示

[[email protected] hmworks]# sh 0906-5
The even number sum : 2550

之前我写这个脚本时是这么写的

#!/bin/bash
#求100以内所有偶数之和;要求循环遍历100以内的所正整数
#author chawan
#date:20160906
declare -i i=1
declare -i sum=0
while [ $i -le 100 ];do
    let sum+=$i
#如果为奇数则跳过该循环,直接进入下一轮判断后面的程序不再执行
    if [ $[${i}%2] -eq 1 ];then
      continue
    fi
    let i++
done
echo  "The even number sum : $sum"

这就是我个人由于对continue的理解不够准确而造成的死循环

由于continue是跳过其所在循环,直接进入下一轮判断,后面的语句都不再执行

当时没注意这点所以错误地把i++放在后面,这就导致若i起始值为奇数那么它就一直在重复执行

这里只要将let sum+=$i与let i++调换为止即可正确执行

………………………………………………………………………………………………………………………

2、break [N]:提前结束循环;

其使用格式

    while CONDTIITON1; do

      CMD1

...

      if CONDITION2; then

         break

      fi

      CMDn

...

    done

break的使用通常是与死循环同时出现的,下面来介绍如何创建死循环

创建死循环:

    while true; do

     循环体

    done

    until false; do

     循环体

    done

………………………………………………………………………………………………………………………

示例:每隔3秒钟到系统上获取已经登录的用户的信息;如果docker登录了,则记录于日志中,并退出;

#!/bin/bash
#每隔3秒钟到系统上获取已经登录的用户的信息;如果docker用户登录,则记录于日志中,并退出脚本
#author chawan
#date:20160906
while true;do
     if who | grep "^docker\>" $> /dev/null;then
         break
     fi
     sleep 3
     echo "docker is not login"
done
echo "docker logged on." >> /tmp/user.log

运行脚本

[[email protected] hmworks]# sh 0906-6
docker is not login
docker is not login
docker is not login
docker is not login
docker is not login
docker is not login

为了验证该脚本,下面我们使用docker用户登陆

docker用户登陆后查看/tmp/user.log文件



循环语句的特殊用法(while及for)

while循环的特殊用法(遍历文件的每一行)

其使用格式

    while read line; do

      循环体

    done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line

………………………………………………………………………………………………………………………

示例:找出其ID号为偶数的所有用户,显示其用户名及ID号;

#!/bin/bash
#找出其ID号为偶数的所有用户,显示其用户名及ID号
#author chawan
#date:20160906
while read line;do
  if [ $[`echo $line | cut -d: -f3`%2] -eq 0 ];then
    echo -e -n "username: `echo $line|cut -d: -f1`\t"
    echo "uid:`echo $line|cut -d: -f3`"
  fi
done < /etc/passwd

运行脚本

………………………………………………………………………………………………………………………

for循环的特殊格式

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)); do

    循环体

done

控制变量初始化:仅在运行到循环代码段时执行一次;

条件判断表达式:在什么条件下进行循环;

控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断;

示例:求100以内所正整数之和

#!/bin/bash
#求100以内所正整数之和
#author chawan
#date:20160906
declare -i sum=0
for ((i=1;i<=100;i++));do
     let sum+=$i
done
echo "The sum is : $sum"

运行脚本,查看结果是否正确

[[email protected] hmworks]# sh 0906-8
The sum is : 5050

for的这种格式减少了代码量,看着更简洁,不过其限制是只适用于有数字出现的循环,若是对某目录下的所有文件进行某种循环的执行就不适应了。



循环嵌套

在本文的最后再以一题体会下循环嵌套的神奇

示例:打印九九乘法表

#!/bin/bash
#打印九九乘法表
#author chawan
#date : 20160906
for((j=1;j<=9;j++));do
   for((i=1;i<=j;i++))do
      echo -e -n "${i}X${j}=$[$i*$j]\t"
   done
echo
done

我在刚刚接触循环嵌套时各种晕,循环嵌套不是没有目的的乱用,而是根据自己的需求有目的的使用,比如要打印99乘法表,首先要分析99乘法表的规律,首先它横行是连续的,通常在遇到连续的内容都会用到循环,再观察我们发现它的列也是连续的,因此又用到一个循环,而99乘法表又是由两个变化的量构成,综上我们就可以确定,需要使用两个变量,这两个变量分别要用到循环,而一个变量又受到另一个变量的限制,因此这个受限的变量就是被嵌套的主。问题分析到这里,我们解决这个问题要用到的工具都找出来了,下面就是靠自己去使用工具解决问题了。我相信大家这点应该都不成问题,问题就分析到这里。




小结

本文主要介绍什么是循环,死循环,bash常用的三种循环语句for、while、until及循环控制语句continue、break

在本文结尾又介绍了while的特殊用法(遍历文件中的每一行),for的c语言格式。

至于什么时候用for什么时候用while需要自己在实际写脚本中细细比较,鉴于本人也是新手,这里就算想细说也只能望洋兴叹。

时间: 2024-11-10 01:14:16

Linux基础之bash脚本进阶篇-循环语句(for,while,until)及其特殊用法的相关文章

Linux基础之bash脚本进阶篇-数组

数组 什么是数组? 计算机中的数组指的是具有相同类型的若干变量按照一定的顺序组织起来的一种数据类型. 通俗点来说数组就是变量的一种,按现在的术语来说就是变量圈子中的一个,只不过这个变量圈子都是相同类型的变量并有一定的组织顺序. 数组的格式 array[key]=value array:表示数组变量的名称 key:表示数组元素的索引又称下标 value:表示key对应的数组元素的值 大体了解了什么是数组,下面就来了解下如何定义数组或如何创建数组 --------------------------

Linux基础之bash脚本进阶篇-函数

函数,什么是函数? 函数的出现最初是在数学中,它的数学定义如下:在某变化过程中有两个变量x,y,按照某个对应法则,对于给定的x,有唯一确定的值y与之对应,那么y就叫做x的函数. 而在计算机中函数的内涵发生了一些变化. 在编程中,为了简化代码量,通常会将经常调用的一些代码模块化,并一一个名字表示,当再次使用该模块时只需要输入该名字,系统会自动去读取该名字所对应的代码模块.因此在计算机中把一段独立功能的代码当做一个整体,并为之命一个名字,命名的代码段即为函数. 虽然此函数非彼函数但函数最本质的意义并

Linux基础之bash脚本编程进阶篇-选择执行语句(if,case)

bash脚本的书写规范简介 看本文需要了解的脚本撰写习惯:bash 开头顶格写#!紧接着写解释器路径/bin/bash 由于bash属于脚本语言,脚本语言的运行方式 解释运行:源代码 --> 运行时启动解释器,由解释器边解释边运行 Linux中的脚本解释器有:zsh,csh,bash,tsh众多shell,不过bash最常用. 第一行写完之后,就可以直接写代码.不过为了便于他人阅读通常会增加如下行: 第二行:#版本信息 第三行:#作者与联系方式 第四行:#版权宣告方式 第五行:#History

Linux基础之bash脚本编程初级-逻辑运算与测试

引言 前面介绍了bash编程的基础变量与算术表达式,本文介绍在脚本中的进阶知识:测试 在bash中测试大体分两部分:条件测试.组合测试. 而条件测试有分:数值测试.字符串测试.文件测试. 组合测试则有两种表达方式.具体是什么表达方式在文章中会有具体展示. 本文实验环境为CentOS7.2 Linux中为什么要学习测试(判断)? 当我第一次学习这部分内容时,觉得好难,好不爽.可是这又是想要继续学习Linux必须要掌握的知识点.为什么?我们在生活中面对各种选择时总要问问自己,我是否应该怎样,不这样会

Linux基础之bash脚本编程初级-变量

什么是变量? 变量最初来源于数学,指的是非固定的值可变化的数通常用拉丁字母表示.在计算机中变量它依旧指的是可变化的数,只不过表现形式有些变化.它指的是变量名+所指向的内存空间. 以下实验环境均在CentOS7.2进行 变量的特点 变量分强类型变量,与弱类型变量 强类型变量:变量需事先声明且需提前定义其变量存储格式 弱类型变量:不需事先声明,不需定义变量存储格式. bash把所有变量统统视作字符型:bash中的变量无需事先声明,相当于,把声明和赋值过程同时实现. 变量名的命名规范: 变量名只能包含

十分钟完成Bash 脚本进阶!列举Bash经典用法及其案例

前言:在linux中,Bash脚本是很基础的知识,大家可能一听脚本感觉很高大上,像小编当初刚开始学一样,感觉会写脚本的都是大神.虽然复杂的脚本是很烧脑,但是,当我们熟练的掌握了其中的用法与技巧,再多加练习,总有一天也会成为得心应手的脚本大神.脚本在生产中的作用,想必小编我不说,大家也都知道,脚本写的6,可以省下很多复杂的操作,减轻自己的工作压力.好了,废话不多说,接下来,就是Bash脚本的用法展示. 一.条件选择.判断(if·.case) 二.四个循环(for.while.until.selec

Bash 脚本进阶,经典用法及其案例

前言:在linux中,Bash脚本是很基础的知识,大家可能一听脚本感觉很高大上,像小编当初刚开始学一样,感觉会写脚本的都是大神.虽然复杂的脚本是很烧脑,但是,当我们熟练的掌握了其中的用法与技巧,再多加练习,总有一天也会成为得心应手的脚本大神.脚本在生产中的作用,想必小编我不说,大家也都知道,脚本写的6,可以省下很多复杂的操作,减轻自己的工作压力.好了,废话不多说,接下来,就是Bash脚本的用法展示. 一.条件选择.判断(if·.case) 二.四个循环(for.while.until.selec

shell脚本进阶篇(上)

shell脚本是我们学习运维的难点,本篇内容简单举例shell脚本的进阶上篇,有任何技术上的指导,知识上的不足都欢迎指出点明. 流程控制 过程式编程语言: 顺序执行   选择执行  循环执行 条件选择if语句 ? 单分支 if 判断条件;then 条件为真的分支代码 fi 双分支 if 判断条件; then 条件为真的分支代码 else 条件为假的分支代码 fi 多分支 if 判断条件1; then 条件为真的分支代码 elif 判断条件2; then 条件为真的分支代码 elif 判断条件3;

VBS基础篇 - 循环语句(3) - For...Next

VBS基础篇 - 循环语句(3) - For...Next 指定循环次数,使用计数器重复运行语句,语法结构如下: 1 2 3 4 5 For counter = start To end [Step step]     [statements]     [Exit For]     [statements] Next 主要参数:        counter:用做循环计数器的数值变量.这个变量不能是数组元素或用户自定义类型的元素.        start:counter的初值.