前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >linux21-shell脚本中的循环操作

linux21-shell脚本中的循环操作

作者头像
北野茶缸子
发布2022-07-07 14:43:49
7420
发布2022-07-07 14:43:49
举报
文章被收录于专栏:北野茶缸子的专栏
  • Date : [[2022-05-01_Sun]]
  • Tags : #linux/index/01
  • 参考:
    • Shell 流程控制 | 菜鸟教程[1]
    • shell编程:for循环 - trafalgar999 - 博客园[2]

前言

最近忽然发现,自己shell 中的循环,似乎除了while read id 以外,忘得一干二净了。

1-for循环

鼎鼎有名的for,自然是每种语言都不可或缺的。

在shell 中,存在两种风格的for 语句。

第一种:

代码语言:javascript
复制
for var in list
do
 commands
done

当list 中的元素包含特殊字符或空格时,可以直接使用 双引号 分割每个元素,或者用转义字符转义。

比如:

代码语言:javascript
复制
$ for i in sad ' asd' dasd \\t;do echo -e $i;done
sad
asd
dasd

我们还可以借用{a..b},实现数字的批量获取:

代码语言:javascript
复制
$ for i in {1..100}; do echo $i >> test.txt; done
$ tail test.txt 
91
92
93
94
95
96
97
98
99
100

因为for 循环需要输入的是一个列表元素,因此,如果尝试直接对文件操作:

代码语言:javascript
复制
$ for i in test.txt 
> do echo $i ; done
test.txt

我们可以利用shell 命令替换的语法(找一期详细介绍一下),比如,我们可以使用反引号(也就是md 语法中代码片段的那个符号),相当于命令在执行时,先完成命令替换中的命令,接着用其结果,作为另一个命令的输入:

代码语言:javascript
复制
$ for i in `head test.txt`; do echo $i; done
1
2
3
4
5
6
7
8
9
10

2-C语言风格的for循环

shell 中的for 循环,需要使用双括号进行选择,其中的结构和C 中的for 非常类似,都是三段式:

代码语言:javascript
复制
for ((a=1; a<10; a++)); do echo $a; done

还可以同时定义多个变量,但三段式中的条件判断,只能设置某一个条件:

代码语言:javascript
复制
for ((a=1, b=10; a<10; a++, b--)); do echo $a' '$b; done

3-while 循环

同样,shell 也提供了两种使用while 的风格。

第一种while 风格,跟其他编程语言类似。

代码语言:javascript
复制
a=4

while (( a>0 )); do echo $a; a=$(( --a )); done
4
3
2
1

上面的语法知识点有很多,比如高级数学表达式(()),不过你只要知道,while 的整个框架就足够了。

不过更为常用的是第二种形式,结合read 语句,read 命令被用来从标准输入读取单行数据,比如我们可以用管道符,读取的内容传递给read:

代码语言:javascript
复制
❯ cat test.txt | while read id; do echo ${id}_loop ;done
1_loop
2_loop
3_loop
4_loop
5_loop
6_loop
7_loop
8_loop
9_loop
10_loop

4-循环控制

和其他编程语言一样,shell 也提供了循环控制的方法,break 和continue。

break 可以直接跳出循环:

代码语言:javascript
复制
❯ a=10
❯ while;do echo $a;a=$(( --a )); if (( a<5 )); then break;fi;done
10
9
8
7
6
5
❯ echo $a
4

当我们使用嵌套循环时,还可以跳出指定的循环层数break n。ps:我实在厌恶写shell 的循环。不想写了。

continue 则是跳出当前的循环。

我们同样可以将循环语法认为是一个主体,所以我们可以对其输出进行重定向或使用管道符号:

代码语言:javascript
复制
❯ cat test.txt
1
2
3
4
5
6
7
8
9
10
❯ cat test.txt| while read id;do echo $id; done | sort -nr
10
9
8
7
6
5
4
3
2
1

其他循环

until 和while 真好相反,while 是满足条件,即命令的状态码不为0 才退出,而until 则是返回的状态码为0 才退出,即条件表达式被满足。其实和语义也非常相符,until 正是知道……才

代码语言:javascript
复制
❯ until (( a <= 3 ));do a=$(( --a )); echo $a; done
9
8
7
6
5
4
3

其他内容

  • 分隔字段符

当使用循环遍历文本文件时,有时候遇到下面情况。如果我们想要遍历每行。却因为空格,拆分了本来一行中的内容。

代码语言:javascript
复制
cat ifs_test.txt
a b
c
d

$ for i in $(cat ifs_test.txt)
> do
>   echo $i
> done
a
b
c
d

这是因为shell中存在特殊的环境变量 IFS ,叫做内部字符分隔符。默认下shell 的分隔符包括:空格、制表符、换行符。

因此如果想要解决上面的问题,就需要修改IFS。IFS=$'\n' ,使shell 只能识别到换行符作为分割点。

总结一下

其实while 和for 完全是足够了的。

  • 如果是遍历数字,for i in 和C 语言风格的for 会很好用;
  • 如果是文件,自然是while read;

事情当然是越简单越好。

此外,shell并不会考虑你的感受的,所以全部的缩进,建议你在如sublime 等编辑器下操作:

或者是感受shell 满满的恶意吧:

当然你如果训练有素,直接靠分号操作,也不是不行:

代码语言:javascript
复制
cat test.txt| while read id;do echo $id; done | sort -nr

参考资料

[1]

Shell 流程控制 | 菜鸟教程: https://www.runoob.com/linux/linux-shell-process-control.html

[2]

shell编程:for循环 - trafalgar999 - 博客园: https://www.cnblogs.com/trafalgar999/p/13121405.html#:~:text=C%20%E8%AF%AD%E8%A8%80%E7%9A%84%20for%20%E5%91%BD%E4%BB%A4%20bash%20shell%20%E4%B9%9F%E6%94%AF%E6%8C%81%E4%B8%80%E7%A7%8D%20for,for%20%28%28variable%20assignment%20%3B%20condition%20%3B%20iteration%20process%29%29

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1-for循环
  • 2-C语言风格的for循环
  • 3-while 循环
  • 4-循环控制
  • 其他循环
  • 其他内容
  • 总结一下
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档