117、【OS】【Nuttx】【周边】效果呈现方案解析:while 循环处理(下)
【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
接之前 blog
【OS】【Nuttx】【周边】效果呈现方案解析:while 循环处理(上)
分析了 while 循环结构,顺便简单的介绍了 POSIX 标准
while 循环处理
首先从 POSIX 基础规范 《The Open Group Base Specifications Issue 7, 2018 edition》中可以看出来
while condition; doaction
done
是其标准语法,在 Bash Shell 中,hile 循环体必然跟着关键字 do 和 done,中间是循环体要执行的动作,如果没有 do … done 结构,只有 while condition 条件判断,可以看下会发生什么
在终端输入
touch test
chmod 777 test
echo '#!/bin/bash
while true;' > test
./test
- 创建一个测试文件 test
- 赋予测试文件 test 可执行权限
- 将下面内容输入到 test 文件,注意这里是 echo ‘…’ 单引号
#!/bin/bash
while true;
- 执行 test 文件
可以发现 Shell 执行会报错,语法错误,缺少结束符 done
如果是在终端中操作,直接在终端输入
while true;
会发现终端没有直接报错
因为 Bash 在交互模式下会尝试等待用户把命令写完整,当输入 while true; 时,Bash 语法器解析到
- while 是一个关键字
- true 是一个命令
- 分号 ; 表示命令结束
此时语法器期待后面跟着 do,于是进入了多行输入模式(显示 >),等待输入更多内容,这是 Bash 的语法延迟检查机制,允许用户在交互模式下跨多行输入命令
在该模式下,可以按 Ctrl + C 强行退出
事实上,只输入一个 while 关键字,也会让 Bash 进入交互模式等待更多输入,因此此时语法不完整
完整的语法必须像规范介绍的一样,出现 do 和 done 才算结束
while condition; doaction
done
在 Bash 终端输入完整的语法之后,Bash 语法器检测到 done 结束符,此时就会开始执行 while 循环体,比如
如果此时有错误语法,比如输入了 sleep(1),Bash 语法器检测到后,会立刻报错,并退出多行输入模式
所以总结一下:
- 在 Bash 脚本中,语法不完整或语法错误,执行该脚本都会在 Bash 终端报错
- 在 Bash 终端交互模式,语法不完整会进入多行输入模式,而语法错误会直接报错
回到这个结构,下面来看下里面的 condition 条件
while IFS= read -r -d '' dir; do...
done
这里面有几个关键点:
- IFS 全称 Internal Field Separator(内部字段分隔符),默认值是空格 ,制表符\t,换行符\n,read 命令会按 IFS 分割输入,这里 IFS= 的作用是临时将 IFS 设为空,防止 read 对输入进行任何分割,这样 read 命令会把整行原样读入变量,并保留空格、制表符等
- read:Bash 内置命令,从用户输入或管道数据读取一行
- -r:禁止反斜杠转义,默认情况下,read 会把 \n 当作换行,\t 当作制表符,使用 -r 后,反斜杠被视为普通字符,这里必须加 -r,不然像 path\name.txt 这样的路径会被错误解析
- -d ‘’:指定分隔符(delimiter)为空字符 null
- dir:变量名,用来存储读取到的内容,每次循环,dir 内容都会被刷新
这种读取模式经常和 find … -print0 一起使用
- find … -print0:用 \0 分隔输出,而不是换行符(默认 -print 是换行符)
- while … -d ‘’:用 \0 读取,和上面一一对应
之前 blog 有详细介绍过 -print0,可以回顾下之前的 blog
【OS】【Nuttx】【周边】效果呈现方案解析:-print0 选项
【OS】【Nuttx】【周边】效果呈现方案解析:-print0 补充(上)
【OS】【Nuttx】【周边】效果呈现方案解析:-print0 补充(中)
【OS】【Nuttx】【周边】效果呈现方案解析:-print0 补充(下)
ok,先分析到这里,下篇 blog 分析 while 循环里面执行的动作