命名约定
函数名
使用小写字母,用下划线分隔单词。使用 :: 分隔库名。
函数名后必须有括号。function 关键字是可选的,
但在整个项目中必须一致使用。
如果你编写的是单个函数,使用小写字母并用下划线分隔单词。如果你编写的是一个包
(Package),使用 :: 分隔包名。但是,用于交互使用的函数可以选择避免使用冒号,
因为它可能会干扰 bash 自动补全。
大括号必须与函数名在同一行(与 Google 其他语言的规范一致), 函数名和括号之间没有空格。
# Single function
my_func() {
…
}
# Part of a package
mypackage::my_func() {
…
}当 ”()” 出现在函数名之后时,function 关键字是多余的,
但它有助于快速识别函数。
变量名
与函数名相同。
循环变量名应与你正在遍历的任何变量类似地命名。
for zone in "${zones[@]}"; do
something_with "${zone}"
done常量、环境变量和 readonly 变量
常量和任何导出到环境的变量应使用大写字母,用下划线分隔,并在文件顶部声明。
# Constant
readonly PATH_TO_FILES='/some/path'
# Both constant and exported to the environment
declare -xr ORACLE_SID='PROD'为了清晰起见,推荐使用 readonly 或 export 而非等效的 declare 命令。
你可以先后执行两者,如:
# Constant
readonly PATH_TO_FILES='/some/path'
export PATH_TO_FILES可以在运行时或条件语句中设置常量,但之后应立即将其设为只读。
ZIP_VERSION="$(dpkg --status zip | sed -n 's/^Version: //p')"
if [[ -z "${ZIP_VERSION}" ]]; then
ZIP_VERSION="$(pacman -Q --info zip | sed -n 's/^Version *: //p')"
fi
if [[ -z "${ZIP_VERSION}" ]]; then
handle_error_and_quit
fi
readonly ZIP_VERSION源文件名
使用小写字母,如需要可用下划线分隔单词。
这是为了与 Google 其他代码风格保持一致:
maketemplate 或 make_template,而不是 make-template。
使用局部变量(Local Variables)
使用 local 声明函数特定的变量。
通过在声明时使用 local,确保局部变量仅在函数及其子函数中可见。
这可以避免污染全局命名空间和无意中设置可能在函数外有意义的变量。
当赋值值由命令替换提供时,声明和赋值必须在不同的语句中;
因为 local 内建命令不会传播命令替换的退出码(Exit Code)。
my_func2() {
local name="$1"
# Separate lines for declaration and assignment:
local my_var
my_var="$(my_func)"
(( $? == 0 )) || return
…
}my_func2() {
# DO NOT do this:
# $? will always be zero, as it contains the exit code of 'local', not my_func
local my_var="$(my_func)"
(( $? == 0 )) || return
…
}函数位置
将所有函数放在文件中常量下方的位置。不要在函数之间隐藏可执行代码。 这样做会使代码难以跟踪,并在调试时产生意外。
如果你有函数,将它们全部放在文件顶部附近。
只有 include 语句、set 语句和常量设置可以在声明函数之前完成。
main
对于足够长且至少包含一个其他函数的脚本,需要一个名为 main 的函数。
为了便于找到程序的起点,将主程序放在名为 main 的函数中作为最底部的函数。
这与代码库的其余部分保持一致,也允许你将更多变量定义为 local
(如果主代码不是函数则无法做到这一点)。文件中最后一行非注释行应该是对 main
的调用:
main "$@"显然,对于简短的线性流程脚本,main 是过度设计的,因此不是必需的。