脚本写一行echo也能写出bug ? glob了解一下

背景

最近处理一个 bug 很有意思,有客户反馈某个配置文件解析失败了,出错的那行的内容就只有一个字母 a

最开始以为是谁改动了处理的脚本,但要到了问题代码中的脚本,比较发现跟库上是一样的。

又经过一番查找,才发现原来是脚本中的一行 echo 引入的。

问题代码

出问题的那行 bash 脚本是这样, echo 一个字符串到某配置文件中。

echo [partition] >> xxx.config

这行平平无奇的代码在大多数人的环境下,确实是正常运行的,但某些情况下会出 bug,那就是当运行脚本的目录下存在特定文件的时候。

复现问题

看看例子,就明白了,其实就是匹配到了文件名。

/$ mkdir /tmp/glob_test && cd /tmp/glob_test  /tmp/glob_test$ echo [partition]  [partition]  /tmp/glob_test$ touch a  /tmp/glob_test$ echo [partition]  a  /tmp/glob_test$ touch o  /tmp/glob_test$ echo [partition]  a o

也就是说出问题的机器上,运行脚本的环境刚好存在一个名为 a 的文件,于是这行脚本的行为就改变了。

本意是写入 [partition] 实际上写入了a

解决也很简单,加上引号。

echo "[partition]" >> xxx.config

glob简介

解决了问题,再回头认识下这个特性。这个叫 glob ,是 bash 的一个特性,可以实现文件名的通配。

最原始可追溯到 UNIX V6,后来就变成了 shell 内建的特性。

当字符串包含了 '?' '*' '[' 的时候就会触发匹配,自动展开成匹配到的文件列表,这个比正则表达式要弱一些,但胜在简单实用。

大家可能经常用到类似于 ls *.c' 之类的功能,这就是 glob 生效的地方。

这里不再详细列出语法,请参考 man 7 glob 或网上诸多文章,例如阮一峰老师就分享过:命令行通配符教程

有一个要注意的地方就是,这个匹配如果失败,就会原样输出,这也是上文的例子在多数情况下能工作的原因。

写在最后

写脚本时该加引号还是得加上的,养成良好的习惯可以少写 bug

另外,虽然 shellcheck 并不能检测到这种情况,但对于提高脚本质量还是很有帮助的,之前也介绍过,可参考:shellcheck 帮助你写出更好的脚本

本文地址: https://www.cnblogs.com/zqb-all/p/12489524.html

公众号: https://sourl.cn/nYkaiK