BASH 的几个常见陷阱

wxie

2020

Return to index

Article published by: wxie

Date of publication: 2020

2021 年已经不太远了。还好拜登赢得了美国大选,地球终于可以换一口气了。

我们接着看自由软件。上次我们讲到了 BASH

的错误处理。这次我们来看看几个初学者容易犯的 BASH 错误——如果不注意,这些错误的后

果可能很严重。

刚开始使用 BASH 的朋友可能还不习惯 unix 的沉默——许多命令没有显式返回,只是默默地

等待或者回到提示符;他们也可能不熟悉有的命令需要至少两个参数,比如 grep。如果

你只输入一个参数:





grep "gnu"



那么,你就可能陷入默默的漫长等待——grep 在等你输入第二个参数!正确的用法是





grep "gnu" foo.txt



或者





cat foo.txt | grep "gnu"



不知道这个就会让生命在等待中错过。

下面的 BASH 命令非常常见





find . -name *.c



你要找到当前目录及其子目录下的 c 文件——也许你要管理一下代码文件。该命令的返回可

能是





./src/main.c




./src/foo.c




./lib/bar.c



也许你想删除其他文件,只保留 c 文件。在删除其他文件之前,你想先确认一下有哪些不

是 c 的文件。于是,你输入命令





find . -not -name *.c



它告诉你





./readme.txt




./lib/other.cpp



你觉得没问题,可以删除。于是,你输入命令





find . -not -name *.c -delete



结果一切如你所想,剩下的文件是





./src/main.c




./src/foo.c




./lib/bar.c



换一种场景,你当前目录里的文件是





.




./readme.txt




./test.c




./lib




./lib/other.cpp




./src




./src/main.c




./src/foo.c




./lib/bar.c



当你执行同样的删除命令时





find -not -name *.c -delete



你的当前目录里就只剩下





.




/test.c



你辛辛苦苦的开发成果就付诸东流了——全删除了。这是因为 BASH 会先把通配符扩展成当前

能够匹配的文件,然后再执行命令。所以上面的命令实际变成了





find . -not -name test.c -delete



后果可想而知。正确的做法是使用单引号





find . -name '*.c'



这样,通配符就不会被解析扩展了。常见的命令lsgrepsedfindawk都会

碰到类似的问题,所以这个引号还是很重要的。

你想搜索一下文件里的浮点数,就是带小数点.的数。于是,你测试以下命令





echo "1234.5678" | grep -Eo "[0-9]+.[0-9]+"



它返回





1234.5678



看来没什么问题。作为一个严谨的开发人员,你通常都至少要有 3 个测试用例,你又输入

命令





echo "1234A5678" | grep -Eo "[0-9]+.[0-9]+"



出乎你所料,它居然返回





1234A5678



你莫名其妙。其实,这是因为.是一个通配符,它可以替代除了换行之外的任意字符。所

以,正确的命令是不解析它(使用\





echo "1234A5678" | grep -Eo "[0-9]+\.[0-9]+"



结果正常了,是空




你有一个文件 foo.txt,其内容是





The usage of `ls`




ls -a




ls -l



你想搜索其中的 ls,没问题,你在 BASH 中输入命令





grep ls foo.txt



结果正常





The usage of `ls`




ls -a




ls -l



你还想搜索带反引号的ls,于是你输入命令





grep `ls` foo.txt



结果输出一堆你始料不及的结果。你觉得可能是要加双引号,于是输入





grep "`ls`" foo.txt



结果什么也没出来。什么原因?因为 BASH 是会解析反引号的——结果是把反引号里的命令结

果输入。如果要避免命令解析,你需要使用单引号把命令引起来





grep '`ls`' foo.txt



结果正常了





The usage of `ls`



BASH 的用法很奇妙,多做测试(至少有三个测试用例)有助于你深刻记忆这些细微之处,

避免严重错误。

Markdown file for this page: https://wxie.codeberg.page/tutorials/tutorial/BASH_的几个常见陷阱.md

Subscribe to RSS for this site

This HTML page was generated by the Untitled Static Site Generator.