Bash,一门典型的面向 Google 编程的语言(类似的还有面向 StackOverflow 编程的 vim),最大的语言特性是其“不确定性原理”(你要么学会了 Bash 了语法,要么写出了能正常运行的 Bash 脚本,但是不能即学会了语法又写出了脚本),你今天刚学会的语法,到了明天就不一定会记得了;今天刚写好的代码,到了明天就不一定能运行了。与其回忆昨天学了什么,还不如直接问 Google。
Bash 学习的深入可真是“从入门到入土”,个人感觉最佳实践应该是把 Bash 作为脚本入口,包一层别的脚本语言(比如 Python),后续工作全交由后者处理。
Bash is Untype
- Bash 没有类型,所以 Bash 所有类型、对象、变量都是 Text/String 文本,没有结构体(或者说唯一的结构体就是空格分隔的文本)。
- if [ $bool ] 其实是判断变量 bool 是不是 Not Empty。
- 因为都是文本类型,所以判断 Number 变量大小、加减,都需要使用配套的命令:-eq/-ne/-gt/-lt。
面向文本编程
- Bash 语言里,一切都是 Text。
- Bash 没有类型,甚至没有动态语言特有的结构,纯靠 Shell 工具解析 Bash 文本并执行相关指令。文本约束性太弱,经常会有意想不到的“惊喜”。
- 处理带有空格的 Var 的时候比较危险,因为空格有可能被当成 Bash 指令分隔符处理。
- sh <bash_file>
或者 eval 的时候,args 是被当成一个文本在解析成入参的。如果 args 包含有 Empty 参数,则该解析后的入参里会漏掉该参数并导致参数位置出现偏移。 - 文本有些场景需要加转义字符但是经常完了但是确没报错,比如:比较大于操作符 › 被当成文本输出操作符执行且返回 true。
- 文本还容易被当成命令执行。
- 抽取 Bash 重复代码段,使用 function 代替也会出现惊喜,特别是方法体里有 loop 以及需要返回值的时候。
- function 方法块内最后的 statement 如果没有作为返回值赋值给一个 var,或者在方法最后使用 echo 来消费,则调用方法后改 statement 的值会作为 bash 指令执行。
Bash 编程最佳实践
- 别思考 Bash 语法,直接 Google 反而更快一些。
- Bash 语法有比较严重的兼容性问题,不仅不同 Bash 版本之间的 Bash 脚本表现可能不同,在不同终端(Shell)上面的运行效果可能也不一样。
- 要复用 Bash 代码能难,最好的实践就是 CAP 编程原则。
- 把 Bash 作为脚本入口,包一层别的脚本语言(比如 Python),后续工作全交由后者处理。