《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令

本章讨论bash shell的循环命令for、while和until

13.1 for命令

重复执行一系列命令在编程中很常见。

bash shell提供了for命令,允许你创建一个遍历一系列值的循环。每次迭代都使用其中一个值来执行已定义好的一组命令。下面是基本格式

for var in list

do

command

done

在list参数中需要提供迭代中要用到的一系列值。会依次迭代下去。每次迭代中,var会包含列表中要用到的一系列值。

do 和 done直接输入的命令可以是一条或多条标准的bash shell命令。

13.1.1 读取列表中的值

每次for命令遍历值列表,它都会将列表中的下一个值赋给$var变量。最后一次迭代后,$var变量的值会在shell脚本中剩余部分一直保持有效。(除非你修改了它)

13.1.2 读取列表中的复杂值

列表值的单引号是个大麻烦。

有两个方法可以解决

1)使用转义字符\。将单引号转义

2)使用双引号来定义用到单引号的值

在某个值两边使用双引号时,shell并不会将双引号当成值的一部分

13.1.3 从变量读取列表

将一系列的值都集中存储在了一个变量中,然后需要遍历变量中的整个列表。

#!/bin/bash

# for test

name1="xcx1 xcx2 xcx3"

name2=$name1" xcx4"

#for name in xc\‘y "xcy‘1 haha" xcy2 xcy3 xcy4 xcy5

for name in $name2

do

        echo "Hi, My name is $name"

done

echo "The last people is $name"

name2包含了用于迭代的标准文本值列表。注意。name2用了另一个复制语句向name2变量包含的以有列表中添(或者说拼接)加了一个值。

13.1.4 从命令读取值

生成列表中所需值的另外一个途径就是使用命令的输出。

可以用命令替换来执行任何能产生输出的命令,然后在for命令中使用该命令的输出。

例子:

新建一个文件states,内容如下:

再建一个test2

#!/bin/bash

file="states"

for state in $(cat $file)

do

        echo "Visit beautiful $state"

done

运行就好了。

for仍然以每次一行的方式遍历的cat命令输出的结果。

13.1.5 更改字段分隔符

1.特殊环境变量IFS:内部字段分割符。定义了bash shell用作字段分隔符的一系列字符。

2.默认情况下会将下列字符当做字段分隔符。1)空格 2)制表符 3)换行符

3. 如果bash shell 在数据中看到了这些字符中的任意一个,它就会假定这表明了列表中一个新数据字段的开始。

在处理包含空格的数据时会比较麻烦。所以需要修改IFS的值。

只识别换行符,就需要这么做:IFS=$’\n’。将这个语句假如脚本中,告诉bash shell在数据值中忽略空格和制表符。

#!/bin/bash

file="states"

IFS=$’\n’

for state in $(cat $file)

do

        echo "Visit beautiful $state"

done

还有一些绝妙用法:假如需要遍历一个文件中用冒号分割的值。就可以IFS=:

如果需要指定多个字符,只需要将它们在赋值行中串起来就行。IFS=$’\n’:;”  将换行符、冒号、分号、双引号作为字段分隔符

13.1.6 用通配符读取目录

可以用for命令来自动遍历目录中的文件。进行此操作时,必须在文件名或路径名中使用通配符。

它会强制使用文件扩展匹配(生成匹配指定通配符的文件名或路径名的过程)。

比如下面的例子:

  1 #!/bin/bash

  2 for file in /home/xcy/shell/*

  3 do

  4         if [ -d "$file" ]  # 加双引号为了解决文件名含有空格的问题

  5         then

  6                 echo "$file is directory"

  7         elif [ -f "$file" ] # 如果文件名有空格,没有双引号就会出错

  8         then

  9                 echo "$file is file"

 10         fi

 11 done

for语句首先使用了文件扩展匹配来遍历通配符生成的文件列表,然后会遍历列表中的下一个文件。可以将任意多的通配符放进列表中。

13.2 C语言风格的for命令

13.2.1 C语言的for命令

以下是bash中C语言风格的for循环的基本格式:

for (( variable assignment ; condition ; interation process ))

例子:

for (( a = 1; a < 10; a++ ))

(1)变量赋值可以有空格

(2)条件中的变量不以美元符开头

(3)迭代过程的算式没有用expr命令格式。

例子:

  1 #!/bin/bash

  2 # C for test

  3 for (( i = 10; i > 0; i-- ))

  4 do

  5         echo "For Test: i = $i"

  6 done

13.2.2 使用多个变量

C语言风格的for命令允许为迭代使用多个变量。循环会单独处理每个变量,可以为每个变量定义不同的迭代过程。

尽管可以使用多个变量,但你只能在for循环中定义一种条件。

例子:

  1 #!/bin/bash

  2 # C for multiple variables test

  3 for (( i=10, b = 0; i > 0; i--, b++ ))

  4 do

  5         echo "For Test: i = $i, b = $b"

  6 done

13.3 while命令

某种意义是if-then和for循环的混杂体。

while命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的退出状态码0.它会在每次迭代的一开始测试test命令。在test命令返回非0退出状态码时,while会停止执行那组命令。test返回0,就接着迭代,否则暂停)

13.3.1 while的基本格式

while test command

do

  other commands

done

关键在于test command的退出状态码要随着循环中运行的命令而改变。否则就会停不下来

例子:用方括号检查循环命令中用的shell的变量的值

  1 #!/bin/bash

  2 i=10

  3 while [ $i -gt 5 ] # 相当于 >

  4 do

  5         echo "i = $i"

  6         i=$[ $i - 1 ]  # 不能用i--

  7 done

13.3.2 使用多个测试命令

可以在while后面接多个测试命令,只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环

例子:

1 #!/bin/bash

2 # multicommand test

3 var=2

4 while echo "var = $var"

5         [ $var -ge 0 ]  # -ge 相当于大于等于 >=

6 do

7         echo "this is inside the loop"

8         var=$[ $var - 1 ]

9 done

结果:

说明每次迭代中所有的命令都会执行,包括测试命令失败的最后一次迭代。

另外,如何指定多个测试命令。每个测试命令都出现再单独的一行上。

13.4 until命令

和while相反。until命令要求你指定一个通常返回非0退出状态码的测试命令。

只有测试命令退出状态码不为0,bash shell才会执行循环中列出的命令。

一旦返回了退出状态码0,循环就结束了。

格式:

until test commands

do

         other commands

done

例子:

  1 #!/bin/bash

  2 # until test

  3 var=100

  4 until [ $var -lt 0 ]  # 满足条件则结束,不满足则进循环

  5 # -eq  ==

  6 # -ge >=

  7 # -lt <

  8 do

  9         echo "until test: var = $var"

 10         var=$[ $var - 25 ]

 11 done

也可以执行多个测试命令,只在最后一个成立时停止。

13.5嵌套循环

循环语句可以在循环内使用任意类型的命令,包括其他循环命令。

注意在循环嵌套时执行次数是两次循环次数相乘。

例子:

  1 #!/bin/bash

  2 var1=3

  3 for (( var1=3; var1>0; var1-- ))

  4 do

  5         echo "for: var1 = $var1"

  6         var2=3

  7         while [ $var2 -gt 0 ]

  8         do

  9                 echo "  while: var2 = $var2"

 10                 var2=$[ $var2 - 1 ]

 11

 12                 var3=3

 13                 until [ $var3 -eq 0 ]

 14                 do

 15                         echo "    until: var3 = $var3"

 16                         var3=$[ $var3 - 1 ]

 17                 done

 18         done

 19 done

13.6循环处理文件数据

通常需要遍历存储在文件中的数据,需要结合两种技术:

1)使用嵌套循环

2)修改IFS环境变量

例子:

  1 #!/bin/bash

  2 # changing the IFS value

  3 IFS.OLD=$IFS

  4 IFS=$‘\n‘  # 分隔符变为换行符

  5 for entry in $(cat /etc/passwd)

  6 do

  7         echo "Values in [$entry]"

  8         IFS=:   # 分隔符变为冒号

  9         for value in $entry

 10         do

 11                 echo "   $value"

 12         done

 13 done

外循环解析一行一行的用户信息。内循环通过冒号分割,解析一个用户的具体信息。

13.7 控制循环

有两个命令可以控制循环内部的情况:

1)break   2)continue

13.7.1 break命令

退出循环的一种简单方法。可以退出任意类型的循环,包括while和until。

下面几种情况可以使用break命令。

1.跳出单个循环

执行break时,它会尝试跳出当前正在执行的循环。

  1 #!/bin/bash

  2 for var in 10 9 8 7 6 5 4 3 2 1

  3 do

  4         if [ $var -eq 5 ]

  5         then

  6                 echo "this is exec break;"

  7                 break

  8         fi

  9         echo "var = $var"

 10 done

这个方法也适用于while和until循环。

2.跳出内部循环

处理多个循环时,break会自动终止你所在的最内层的循环。

内层循环终止了,外层循环依然会继续执行。

3.跳出外部循环

有时你在内部循环,但需要停止外部循环。break命令接受单个命令行参数。

break n

n指定了要跳出的循环层级。默认情况下n为1.表示跳出当前循环。

若为2,就表示跳出上一级的外部循环。

例子:

1 #!/bin/bash

  2 for(( i=5; i>0; i-- ))

  3 do

  4         echo "outer loop: i = $i"

  5         for(( j = 0; j < 100; j++ ))

  6         do

  7                 echo "inside loop: j = $j"

  8                 if [ $j -eq 5 ]

  9                 then

 10                         break 2 # 跳出上一级循环

 11                 #       break # 跳出当前循环

 12                 fi

 13         done

 14 done

13.7.2 continue命令

提前终止某次循环中的命令,不会完全终止整个循环。

例子:

  1 #!/bin/bash

  2 for(( i=0; i < 10; i++ ))

  3 do

  4         if [ $i -gt 4 ] && [ $i -lt 8 ]

  5         then

  6                 continue

  7         fi

  8         echo "haha i = $i"

  9 done

注意:这个会跳过剩余的命令,如果在剩余的命令中要对测试条件变量进行改变就会出问题。这里需要留个心眼。

也可以通过命令行参数指定要继续执行哪一级循环。 continue n

  1 #!/bin/bash

  2 for(( i=0; i < 5; i++ ))

  3 do

  4         echo "out loop; i = $i"

  5         for(( j=0; j<4; j++ ))

  6         do

  7                 echo "          inside loop +++ j = $j"

  8                 if [ $j -eq 2 ]

  9                 then

 10                         continue 2  #继续上一级循环 还可以不接2,表示继续当前循环

 11                 fi

 12                 echo "          inside loop --- j = $j"

 13         done

 14 done

注意break和continue的区别:

break用于完全结束一个循环,后面的循环也不执行了。

continue用来结束当前循环,后面的循环还会执行。

比如:

for(i = 0; i < 10; i++)

do

         if [ $i –eq 5]

         then

                   break   # 6 , 7 , 8 ,9 就都不会打印了,结束了。

# continue # 仅仅不打印5

         fi

echo “i = $i”

done

13.8 处理循环的输出

直接上例子吧。直接在done后面接 > xxx.txt

13.9 实例

13.9.1 查找可执行文件

找出系统中有哪些可执行文件可供使用,只找PATH环境变量中所有的目录就行了

例子:

  1 #!/bin/bash

  2 # find files in the PATH

  3 IFS=:

  4 for folder in $PATH   # 将各个目录放入folder

  5 do

  6         echo "$folder"

  7         for file in $folder/*   # 迭代指定目录中的所有文件

  8         do

  9                 if [ -x $file ]  # 检查是否有可执行权限

 10                 then

 11                         echo "    $file"

 12                 fi

 13         done

 14 done

13.9.2 创建多个用户账户

让系统管理员更轻松。用脚本创建用户

1.先建立一个文本,里面放用户id和name。用逗号分隔

2. 再去读取上述文件中的信息

while IFS=‘,‘ read -r userid name

这个还是蛮有技巧的。read会自动读取读取.csv文本文件的下一行内容,不需要再写一个循环来处理。

read返回false时(就是读取完了)while就会退出,妙哉。

代码如下:

  1 #!/bin/bash

  2 # shell add user account

  3 input="users.csv"

  4 while IFS=‘,‘ read -r userid name # 读取里面的数据,IFS要设为逗号

  5 do

  6         echo "adding id:$userid  name:$name"

  7         useradd -c "$name" -m $userid

  8 done < "$input"

执行需要sudo权限。

13.9.2 再删除创建的用户

代码如下:

  1 #!/bin/bash

  2 # xcy test, del user

  3 IFS=$‘\n‘

  4 for user in $(cat /etc/passwd)

  5 do

  6 #       echo "$user"

  7         IFS=:

  8         for value in $user

  9         do

 10                 if [[ $value == xiaochongyong* ]]  # 这个*有点通配符的意思

 11                 then

 12                         echo "Userid: $value"

 13                         userdel $value

 14                 fi

 15                 break

 16         done

 17 done

注意那个break,因为/etc/passwd第一条就是userid,这里读取完userid就退出当前循环。

时间: 2024-10-13 02:58:08

《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令的相关文章

《Linux命令行与shell脚本编程大全》23章24章

第二十三章 使用其他shell bash shell是linux发行版中最广泛使用的shell.但是它并不是唯一的选择,还有其他的shell可以供你选择. 23.1 什么是dash shell 百度百科上说:Dash shell是一个Unix shell,比Bash shell小的多,符合POSIX标准. 下面是书上的: dash shell是作为debian linux发行版的一部分开发的,主要出现在Ubuntu linux发行版中.它是Bourne shell的精简版.所以它并不像bashs

《Linux命令行与shell脚本编程大全》学习笔记(转)

第一部分:Linux命令行<Linux命令行与shell脚本编程大全> 第一章:初识Linux shell<Linux命令行与shell脚本编程大全> 第二章:走进shell<Linux命令行与shell脚本编程大全> 第三章:基本的bash shell命令<Linux命令行与shell脚本编程大全> 第四章:更多的bash shell命令<Linux命令行与shell脚本编程大全> 第五章:使用Linux环境变量<Linux命令行与she

&lt;&lt;linux命令行与shell脚本编程大全&gt;&gt;学习笔记(1)

一章初识linux shell 一.什么是linux 1.linux系统可大致划分为四部分: l Linux内核 l GNU工具组件 l 图形化桌面环境 l 应用软件 在linux系统里,这四部分中的每一部分都扮演着一个特别的角色,但如果将他们分开,每一部分都没太大的作用. 1)探究linux内核 Linux系统的核心是内核,内核控制着计算机系统上的所有硬件和软件,必要时分配硬件,有时需要执行软件. 内核基本负责以下四项主要功能: l 系统内存管理 l 软件程序管理 l 硬件设备管理 l 文件系

【持续更新中】Linux命令行与Shell脚本编程大全(第3版)读书笔记12-20章

<Linux命令行与Shell脚本编程大全(第3版)>读书笔记 第十二章 使用结构化命令 根据条件使脚本跳过某些命令,这样的命令称为结构化命令(structured command).结构化命令允许改变程序执行的顺序. If-then语句: If command Then Commands Fi 如果if后的command执行退出码是0(也就是执行成功了),then后面的语句就会被执行. 也可以写成: If command; then Commands Fi 注意了,if后的command结果

Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]

此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M) 原文地址:https://www.cnblogs.com/pluse/p/9408724.html

《Linux命令行与Shell脚本编程大全第2版.布卢姆》pdf

下载地址:网盘下载 内容简介  · · · · · · 本书是一本关于Linux 命令行与shell 脚本编程的全面教程.全书分为四部分:第一部分介绍Linuxshell 命令行:第二部分介绍shell 脚本编程基础:第三部分深入探讨shell 脚本编程的高级内容:第四部分介绍如何在现实环境中使用shell 脚本.本书不仅涵盖了详尽的动手教程和现实世界中的实用信息,还提供了与所学内容相关的参考信息和背景资料. 本书内容全面,语言简练,示例丰富,适合于linux 系统管理员及Linux 爱好者阅读

《Linux命令行与shell脚本编程大全 第3版》

第一部分 Linux 命令行 第1章  初识Linux she1.1   什么是Linux 21.1.1 深入探究Linux 内核 31.1.2 GNU 工具 61.1.3 Linux 桌面环境 81.2   Linux 发行版 121.2.1 核心Linux 发行版 131.2.2 特定用途的Linux 发行版 131.2.3 Linux LiveCD 141.3   小结 15 第2章  走进shell2.1   进入命令行 162.1.1 控制台终端 172.1.2 图形化终端 172.2

《Linux命令行与shell脚本编程大全》第二十二章 gawk进阶

gawk是一门功能丰富的编程语言,你可以通过它所提供的各种特性来编写好几程序处理数据. 22.1 使用变量 gawk编程语言支持两种不同类型的变量: 内建变量和自定义变量 22.1.1 内建变量 gawk程序使用内建变量来引用程序数据里的一些特殊功能 1.字段和记录分隔符变量 数据字段变量:允许你使用美元符和字段在该记录中的位置值来引用记录对应的字段. 要引用第一个字段就用变量$1,第二个就用$2,-.以此类推. 数据字段是由分隔符来划定的.默认字段分隔符是一个空白字符,也就是空格或者制表符.

【更新完毕】Linux命令行与Shell脚本编程大全(第3版)读书笔记21-26章

第二十一章 sed进阶 N:将数据流中的下一行加进来创建一个多行组(multiline group)来处理. D:删除多行组中的第一行. P:打印多行组中的第一行. sed '/header/{n ; d}' data.txt 首先匹配有header的行,然后n表示移动到文本的下一行,然后进行删除.然后继续搜索data.txt中包含header的行,继续之前的流程. 加入有个文本的内容如下: [[email protected] ~]# cat data.txt On Tuesday, the

《Linux命令行与Shell脚本编程大全(第3版)》读书笔记

第一章 初始Linux Shell Linux可以划分为4个部分: - Linux内核 - GNU工具 - 图形化桌面环境 - 应用软件 Linux系统的核心是内核.内核控制着计算机系统上的所有硬件和软件,在必要时分配硬件,并根据需要执行软件. 内核主要负责以下4种功能: - 系统内存管理 - 软件程序管理 - 硬件设备管理 - 文件系统管理 操作系统内核的主要功能之一就是内存管理.内核不仅管理服务器上的可用物理内存,还可以创建和管理虚拟内存(即实际并不存在的内存). 内核通过硬盘上的存储空间来