更多互联网新鲜资讯、工作奇淫技巧关注原创【飞鱼在浪屿】(日更新)
bash是一个很好的交互式shell。bash的优点之一是它没有被编译,对用户透明。比如你无法从Go二进制文件中读取到Go源代码。
但bash代码陷阱是可读性/维护性的噩梦,这与大多数人不了解Bash陷阱的事实有关系。你也无法知道原始作者/将来的维护者是否知道哪些陷阱。
Bash陷阱举例:
- cp $file $target
如果碰巧事先知道$file和$target中没有空格或通配符。如果不确定,务必加个双引参数。
cp -- "$ file" "$target"
没有双引号,您将得到类似
cp 01 - Don't Eat the Yellow Snow.mp3 /mnt/usb
这将导致错误:cp: cannot stat `01': No such file or directory。
如果$ file中包含通配符(*或?或[),则在存在匹配通配符的文件时,它们将被扩展。使用--的目的是排除这种情况:如果“$文件”恰好是以-开头,那么CP会认为是一个选项。
有经验的脚本编写者始终使用引号,除非在少数情况下(从立即代码上下文中绝对可以明显看出某个参数包含有保证的安全值)。
- echo $foo
这个看起来没问题的命令实则有问题。因为$foo没有被引用,所以它不仅会受到空格的限制,而且还会受到文件通配符的影响。这些变量还可以包含‘-’。
msg="Please enter a file name of the form *.zip" echo $msg
该消息被分解为单词,并且所有的通配符都被扩展,例如* .zip。用户可能会看到下列输出
Please enter a file name of the form freenfss.zip lw35nfss.zip
几个写法的区别:
var="*.zip" # var 包含 asterisk, a period, and the word "zip" echo "$var" # 输出 *.zip echo $var # 输出 the list of files which end with .zip
实际上,这种写法不能绝对安全地使用echo命令。如果变量包含-n,则echo将认为是一个选项,而不是要打印的数据。打印变量值的唯一绝对确定的方法是使用printf:
printf "%s" "$foo"
- $foo=bar
不能通过在变量名称前加$来分配变量。这不是perl。
- foo = bar
分配变量时不能在=周围加空格。这不是C。当编写foo = bar时,shell将其分为三个单词。第一个单词foo被用作命令名称。第二和第三个成为该命令的参数。
同样,以下也是错误的:
foo= bar # 错误! foo =bar # 错误! $foo = bar; # 完全错误! foo=bar # 正确. foo="bar" # 推荐写法,最完美.
- cd /foo;bar
如果不检查cd命令中的返回是否成功,则可能最终在错误的位置执行bar。如果例如bar恰巧是rm -f *,那么这可能是一个重大灾难。
必须始终检查cd命令中的错误。最简单的方法是:
cd / foo && bar
如果cd之后不止一个命令,最好这样写:
cd /foo || exit 1 bar baz bat ... # Lots of commands.
更改目录失败,会带有带有stderr消息"bash: cd: /foo: No such file or directory"。但是,如果要在stdout中添加自己的消息,则可以使用命令分组:
cd /net || { echo >&2 "Can't read /net. Make sure you've logged in to the Samba network, and try again."; exit 1; } do_stuff more_stuff
请注意,'{'和echo之间有一个空格,'}'前必须有一个';'。也可以编写die函数。
某些人还喜欢启用set -e使其脚本在返回非零的任何命令时中止。因为许多常见命令对于警告条件可能会返回非零,因此你可能不想将其视为致命的错误而退出。
顺便说一句,如果要在Bash脚本中大量更改目录,请阅读push,popd和dirs上的Bash帮助。也许编写的用于管理cd和pwd的所有代码都是完全不必要的。
更多Bash陷阱
查看:https://mywiki.wooledge.org/BashPitfalls
实用工具Shellcheck:修复陷阱
下载地址:https://github.com/koalaman/shellcheck
Shellcheck使代码远离Bash / shell的“怪异”部分,并会愉快地建议更改正确的代码。
ShellCheck的目标是:
- 指出并弄清楚典型的初学者的语法问题,这些问题会导致shell发出错误的错误消息。
- 指出并弄清楚典型的中级语义问题,这些问题会导致Shell的行为异常和违反直觉。
- 指出可能在将来的情况下导致高级用户的其他正常工作脚本失败的细微警告和陷阱。
使用ShellCheck:
可以直接在各种编辑器中查看ShellCheck建议。
- Vim,通过ALE(https://github.com/dense-analysis/ale),Neomake(https://github.com/neomake/neomake)或Syntastic(https://github.com/vim-syntastic/syntastic):
- VSCode,通过vscode-shellcheck(https://github.com/timonwong/vscode-shellcheck)。
- CentOS的EPEL库安装方法:
yum -y install epel-releaseyum install ShellCheck
- Fedora安装方式
dnf install ShellCheck
- 还有更多安装方式查看github的README:https://github.com/koalaman/shellcheck
命令直接check程序脚本示例: