最近处理一个 bug
颇有意思,有客户反馈某个配置文件解析失败了,出错的那行的内容就只有一个字母 a
。html
最开始觉得是谁改动了处理的脚本,但要到了问题代码中的脚本,比较发现跟库上是同样的。正则表达式
又通过一番查找,才发现原来是脚本中的一行 echo
引入的。shell
出问题的那行 bash
脚本是这样, echo
一个字符串到某配置文件中。bash
echo [partition] >> xxx.config
这行平平无奇的代码在大多数人的环境下,确实是正常运行的,但某些状况下会出 bug
,那就是当运行脚本的目录下存在特定文件的时候。url
看看例子,就明白了,其实就是匹配到了文件名。命令行
/$ 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
的文件,因而这行脚本的行为就改变了。code
本意是写入 [partition]
实际上写入了a
htm
解决也很简单,加上引号。blog
echo "[partition]" >> xxx.config
解决了问题,再回头认识下这个特性。这个叫 glob
,是 bash
的一个特性,能够实现文件名的通配。教程
最原始可追溯到 UNIX V6
,后来就变成了 shell
内建的特性。
当字符串包含了 '?' '*' '['
的时候就会触发匹配,自动展开成匹配到的文件列表,这个比正则表达式要弱一些,但胜在简单实用。
你们可能常常用到相似于 ls *.c'
之类的功能,这就是 glob
生效的地方。
这里再也不详细列出语法,请参考 man 7 glob
或网上诸多文章,例如阮一峰老师就分享过:命令行通配符教程
有一个要注意的地方就是,这个匹配若是失败,就会原样输出,这也是上文的例子在多数状况下能工做的缘由。
写脚本时该加引号仍是得加上的,养成良好的习惯能够少写 bug
。
另外,虽然 shellcheck
并不能检测到这种状况,但对于提升脚本质量仍是颇有帮助的,以前也介绍过,可参考:shellcheck 帮助你写出更好的脚本