Linux 命令行与 shell 脚本编程大全 13 更多的结构化命令

介绍能够控制 shell 脚本流程的结构化命令

更多精彩

导览

  1. 和 Java 、JS 一样,在 shell 脚本中也可以使用 forwhile 循环
  2. until 循环则是和 while 循环在条件判断规则上完全相反的的一种循环操作
  3. break 命令支持直接终止循环,同时还可以通过 break n 指定要终止的循环层级
  4. contiune 命令支持直接中止当前循环,直接进入下次循环,同时还可以通过 continue n 指定要中止的循环层级
  5. 在循环结束后可以再最后使用管道干预脚本的输出结果,可以使用重定向将脚本的输出导入文件

13.1 for 命令

  1. 在 shell 中可以使用 for 命令来循环遍历一系列值,基本语法如下:
    • 使用效果和其他语法的 for 循环基本一致
for var in list
do
  commands
done

13.1.1 读取列表的值

  1. for 循环最基本的用法就是读取列表的值,如下图
    • name 是在 for 循环中声明的局部变量,但是在循环结束后,该变量依旧可以正常被访问,或者被修改

13.1.2 读取列表中的复杂值

  1. 如果需要被遍历的列表中的值存在一些复杂的组合,例如:单引号、双引号、空格
  2. 这个时候就需要先对这些特殊符号进行转义,方式有以下两种
    • 使用反斜线将单引号转义
    • 使用双引号将用到单引号、空格的值进行包裹
  3. 写一个简单的例子演示一下,如下图
    • 需要注意的是,在第一个循环中的列表,连续使用了两个没有被转义的单引号,得到了如下的输出结果,如果这里只使用了一个单引号,例如 macbook's cpu is ,造成的错误将会更严重过,会影响整个 shell 脚本无法正常输出结果

13.1.3 从变量读取列表

  1. 将需要被循环的列表存储到变量中,再通过 for 循环进行遍历输出,会更美观,如下图
    • 变量不仅可以接受待输出的列表值,还能对列表值进行拼接
    • 不过这种表现形式在其他语言中更像是字符串而已,不用介意,这就是 shell 的方式


13.1.4 从命令读取值

  1. 可以用命令替换来执行任何可能产生输出的命令,然后在 for 循环的 in 关键字后使用该命令的输出,如下图
    • 变量 directory 存储了一个目录,然后再 for 循环中使用 $(ls $directory) 输出这个目录的内容

13.1.5 更改字段分隔符

  1. for 循环之所以能将字符串的空格作为列表元素的分隔符,是因为系统中存在 内部字段分隔符( Internal Field Separator ,IFS ) 的全局环境变量
  2. IFS 环境变量定义了 shell 作为字段分隔符的多个具体字符,默认情况下,有以下几种
    • 空格
    • 制表符
    • 换行符
  3. IFS 环境变量可以在 shell 脚本中进行临时修改,如下图
    • 下面这个例子中,将 IFS 的值改为只能识别换行符,所以就能顺利的通过循环把每行的内容输出


  4. 如果想要为 IFS 指定多个值,可以直接使用 IFS=$'\n':;" 即可
    • 这就表示换行符、冒号、分号、双引号都会被识别为字段分隔符

13.1.6 用通配符读取目录

  1. 在使用 for 循环时,就算不通过 ls 命令( 在 13.1.4 中有演示 )也能读取目录的内容,使用 文件扩展匹配 即可,如下图
    • 其实就是在路径最后使用通配符


  2. for 循环中还可以同时指定多个目录,实现对输出结果进行拼接的效果,如下图
    • 由于输出的内容太多,最后执行的时候通过 | head 命令只显示了头部的几条信息

13.2 C 语言风格的 for 命令

13.2.1 C 语言的 for 命令

  1. 在 shell 中可以使用和 C 语言风格类似的 for 命令,基本语法如下
    • C 语言我没学过,但这种风格其实和 Java 、JS 中也是一样的
    • 这样做的好处就在于可以实现当前循环进度的输出
for (( variable assigment ; condition ; iteration process ))
do
  commands
done

for (( a = 1 ; a < 10 ; a++ ))
do
  echo "a : $a"
done
  1. 上述的 for 命令语法在以下几个方面没有遵循 shell 标准( 但其实我觉得 shell 没有啥标准,整个 Linux 中的命令风格都是各异的,这可能也是开源导致的吧 )
    • 变量赋值可以有空格
    • 在条件中调用变量时,不需要通过美元符号开头
    • 迭代过程的算式不需要使用 expr 命令
  2. 写一个简单的例子演示一下,如下图


13.2.2 使用多个变量

  1. 在这种风格的 for 循环中,可以在条件中定义多个变量,如下图
    • 可以看到,在变量定义时,同时指定了变量 a 和 b ,并在最后规定了 a 和 b 的迭代方式
    • 但需要注意的是,就算可以定义多个变量,但循环结束的条件只能有一个

13.3 while 命令

  1. while 命令的使用效果和 Java 、JS 中的也基本一致

13.3.1 while 的基本格式

  1. 当 condition 返回非零的退出状态码时,循环就会结束,否则循环将一直进行
while [ condition ]
do
  commands
done
  1. 写一个简单的例子演示一下,如下图
    • 变量 num 初始值为 1
    • 循环结束的条件是 num 小于 10
    • 符合循环条件时,num 每次都会在输出后,累加 1 ,累加的方式是在第 12 章中学到的使用双括号赋值
    • 最后当 num 输出到 9 时,累加后等于 10 ,则无法再次循环


13.3.2 使用多个测试命令

  1. while 命令可以在条件语句中定义多个 test 命令,但只有最后一个命令会被作为 检测循环是否结束 的条件,如下图
    • 可以看到,在条件中定义了两个测试命令,需要注意的是,每个测试命令都必须独占一行
    • 其他内容都和上一个 shell 脚本没有区别,但是在输出时,最后会多输出一个 10 ,这也就是 while 命令支持多个测试命令的意义所在了

13.4 until 命令

  1. until 命令的效果和 while 命令正好相反,但两者的基本语法一致
    • while 命令是当条件返回非零时,就结束
    • until 命令则是当条件返回零时,就结束
  2. 写一个简单的例子演示一下,如下图
    • 可以看到,当 until 命令使用了和之前 while 命令一致的条件判断时,循环体根本无法进入
    • 但当使用了之前 while 命令相反的条件判断时,循环体就顺利进入了

13.5 嵌套循环

  1. 嵌套循环( Nested Loop ) 其实就是多个 forwhileuntil 命令嵌套在一起
    • 被嵌套的叫 内部循环( Inner Loop )
  2. 写一个简单的例子演示一下,如下图


13.6 循环处理文件数据

  1. 这个内容其实在上文中的 13.1.5 更改字段分隔符 小节中就有演示
  2. 这里写一个稍微复杂一点的升级版演示一下,如下图
    • 在读取文件之前,将 IFS 的值改为了只识别换行符
    • 在循环中输出每行的内容后,又将 IFS 的值改为只识别空格
    • 这个时候将每行的数据再次循环,就可以得到每行的具体字符


13.7 控制循环

13.7.1 break 命令

  1. 在循环中使用 break 命令可以直接退出循环,在 forwhileuntil 中都可以使用

13.7.1.1 退出单个循环

  1. 可以看到,按照正常的循环逻辑,循环体应该可以执行 10 次,但是由于添加了当值等于 5 时就执行 break 命令的条件判断,所以在值等于 5 时,循环就停止了

13.7.1.2 退出内部循环

  1. 可以看到,本来外部循环可以执行 5 次,并且在值小于 3 时,每次外部循环执行时,内部循环都可以执行
  2. 但在第一次外部循环中,内部循环执行两次后,就由于条件判断被中断了


13.7.1.3 从内部循环直接退出外部循环

  1. break 命令支持使用 break n 指定循环的层级,表示会直接退出 n 层的循环体,如下图
    • 可以看到,shell 脚本的内容和上一个例子基本一致,唯一的修改就是内不循环的 break 改成了 break 2
    • 在执行脚本后,之前内部循环触发 break 后,这次造成的结果是整个 shell 脚本的终止

13.7.2 continue 命令

  1. 在循环中使用 continue 命令可以直接中止当前循环,直接进入下一次循环,在 forwhileuntil 中都可以使用
  2. 但是在 whileuntil 中使用 continue 时需要注意,不能把 continue 放在迭代条件之前,否则就会造成无限循环,如下图
    • 原本 while 循环的条件判断是当 num 小于 5 时,就一直循环,每次循环 num 都会加 1 ,所以一共会循环 5 次
    • 但是在 num 的累加操作 (( num = $num + 1 )) 之前增加了一个当 num = 2 时就 continue 的操作
    • 这就导致当 num 等于 2 时,当前循环就会被中止,直接进入下一次循环,而 num 的累加操作每次都没有被执行
    • 最后就无限循环了


  3. continuebreak 一样,也可以通过指定层级来跳过对应的层级的循环,如下图
    • 本来外部循环会循环 5 次,并且每次外部循环时,内部循环都会循环 5 次
    • 但是由于 continue 2 的加入,当内部循环的值等于 2 时,外部循环也会被跳过

13.8 处理循环的输出

  1. 在循环的 done 关键字之后可以使用管道或者重定向操作
  2. 结合管道的操作在 13.7.2 continue 命令 中已经有演示,效果就是可以对脚本的输出进行干预
    • 不过这个演示中是将管道放在了脚本执行时
    • 也可以将管道放在脚本内部,done 关键字之后
  3. 结合重定向的操作则是可以将脚本的输出重定向到文件中,如下图
    • 在循环结束后通过 > result 将输出结果重定向到 result 文件中
    • 可以看到,脚本执行后终端没有输出任何语句
    • 查看当前目录可以看到出现了一个 result 的文件,里面的内容就是刚才执行脚本的输出内容


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容