赞
踩
原文链接
英文原文:https://google.github.io/styleguide/shellguide.html
中文原文:https://zh-google-styleguide.readthedocs.io/en/latest/google-shell-styleguide/
手抄笔记用于后续查阅。
❕Tip |
可执行文件应该没有扩展名(强烈建议)或者使用.sh扩展名。库文件必须使用.sh作为扩展名,而且应该是不可执行的 |
平时脚本建议 chmod u+x script_name
给脚本添加执行权限,不用添加扩展名(Linux外编辑器可添加,如notepad++
编辑保存为.sh扩展名文件可以帮助检查语法错误)
❕Tip |
每个文件的开头是其文件内容的描述。 |
每个文件必须包含一个顶层注释,对其内容进行简要概述。版权声明和作者信息是可选的
例如
#!/bin/bash
#
# 程序启动脚本
❕Tip |
任何不是既明显又短的函数都必须被注释。任何函数无论其长短和复杂性都必须被注释。 |
所有的函数注释应该包含:
例如
#!/bin/bash # # 启动程序脚本 APP_NAME="Cluster_1" ########################### # 程序启动函数 # 全局变量: # APP_NAME:应用名称 # 参数: # 无 # 返回值: # 无 ########################### start(){ # TODO }
❕Tip |
注释你代码中含有技巧、不明显、有趣的或者重要的部分。 |
针对某行复杂命令平时可以进行单行注释。
❕Tip |
使用TODO注释临时的、短期解决方案的、或者足够好但不够完美的代码。 |
如果在实现时候觉得代码有缺陷用TODO注释起来。
TODO注释应该包含全部大写的字符串TODO,接着是括号中你的用户名。冒号是可选的。最好在TODO条目之后加上bug或者ticket的序号。
例如
# TODO(曹曹曹老板来了):此处可能存在不匹配的未知场景错误(bug ###)
❕Tip |
缩进两个空格,没有制表符。 |
这一点很重要,平时代码过程忌讳制表符缩进,统一使用两个空格。
❕Tip |
行的最大长度是80个字符。 |
❕Tip |
请将; do,; t hen和while,for,if放在同一行。 |
循环结构尽量一次写完整再写循环体语句。
例如
# for循环语句
for fir in ${dirs_to_cleanup}; do
if [[ -d "${ORACLE_SID}" ]]; then
log_date "Cleaning up old files in ${dir}/${ORACLE_SID}"
rm "${dir}/${ORACLE_SID}"*
if [[ "$?" -ne 0 ]]; then
error_message
fi
else
mkdir -p "${dir}/${ORACLE_SID}"
if [[ "$?" -ne 0 ]]; then
error_message
fi
fi
done
这里有几个细节:
if [[ "$?" -ne 0 ]]
需要和[ ]
留有一个空格(必须)if
语句使用的 [[ ]]
而不是 [ ]
❕Tip |
- 通过两个空格缩进可选项。 |
- 在同一行可选项的模式右圆括号之后和结束符;;之前各需要一个空格。 |
- 长可选项或者多命令可选项应该被拆分成多行,模式、操作、和结束符;;在不同的行。 |
匹配表达式比case和esac缩进一级。多行操作要再缩进一级。一般情况下,不需要引用匹配表达式。模式表达式前面不应该出现左括号。避免使用;&和;;&符号。
例如
# 匹配不同命令执行不同的函数
case "${input}" in
start)
echo "开始启动程序..."
start ${APP_NAME}
;;
stop)
echo "开始停止程序..."
stop ${APP_NAME}
;;
*)
error "未知表达式。"
;;
esac
❕Tip |
按优先级顺序:保持跟你所发现的一致;引用你的变量;推荐用${var}而不是$var |
❕Tip |
除非需要小心不带引号的扩展,否则总是引用包含变量、命令替换符、空格或shell元字符的字符串。 |
使用变量时尽量带上引号,即 "${val}"
$@
除非你有特殊的原因需要使用$*
。❕Tip |
使用$(command)而不是反引号`command`。 |
嵌套的反引号要求用反斜杠转义内部的反引号。而$(command)形式嵌套时不需要改变,而且更易于阅读。
例如
# 倾向于这种
var="$(command "$(command)")"
# 而不是这种
var="`command \`command\``"
❕Tip |
推荐使用[[ ... ]]而不是[,test,和/usr/bin/[。 |
因为在[[和]]之间不会有路径名称扩展或单词分割发生,所以使用[[ … ]]能够减少错误。而且[[ … ]]允许正则表达式匹配,而[ … ]不允许。
❕Tip |
尽可能使用引用,而不是过滤字符串。 |
Bash足以在测试中处理空字符串。所以,请使用空(非空)字符串测试,而不是填充字符,使得代码更易于阅读。
例如
# 推荐 -- 匹配字符串 if [[ "${my_var}" = "some_string"]]; then # TODO fi # 推荐 -- 判断字符串是否为空 if [[ -z "${my_var}" ]]; then # TODO fi # 推荐 -- 判断字符串不为空 if [[ -n "${my_var}" ]]; then # TODO fi # 不推荐 -- 匹配字符串 if [[ "${my_var}X" = "some_stringX"]]; then # TODO fi # 不推荐 -- 判断字符串是否为空 if [[ "${my_var}" = "" ]]; then # TODO fi
❕Tip |
当进行文件名的通配符扩展时,请使用明确的路径。 |
因为文件名可能义-开头,所以使用扩展通配符./*比 * 来得安全的多。
❕Tip |
应该避免使用eval。 |
当用于给变量赋值时,Eval解析输入,并且能够设置变量,但无法检查这些变量时什么。
❕Tip |
请使用过程替换或者for循环,而不是管道导向while循环。在while循环中被修改的变量是不能传递给父shell的,因为循环命令时在一个子shell中运行个的。 |
例如
# 推荐 while read count filename; do total+="${count}" last_file="${filename}" done << (your_command | uniq -c) # 不推荐 last_line='NULL' your_command | while read line; do last_line="${line}" done # 会输出NULL,因为管道命令 last_line="${line}" # 是在子shell中进行的,而父shell中last_line变量还是NULL echo "${last_line}" #
❕Tip |
使用小写字母,并用下划线分割单词。使用双冒号::分割库。函数名之后必须有圆括号。关键词function是可选的,但必须在一个项目中保持一致 |
当函数名后存在( )时,关键词function是多余的。但是其促进了函数的快速辨识。
❕Tip |
如函数名。 |
❕Tip |
全部大写,用下划线分割,声明在文件的顶部。 |
❕Tip |
小写,如果需要的话使用下划线分割单词。 |
注意这里,源文件名是采用小写而不是大写
❕Tip |
使用local声明特定功能的变量。声明和赋值应该在不同行 |
例如
my_func2(){
local name="$1"
# 声明和赋值应该在不同行
local my_var
my_var="${my_func}" || return
# 不推荐这种
# 当赋值的值由命令替换时,声明和赋值必须分开。因为内建的 local 不会从命令替换中传递退出码
local my_var="${my_func}"
}
❕Tip |
总是检查返回值,并给出信息返回值 |
对于非管道命令,使用$?或直接通过一个if语句来检查保持其简洁
例如
if ! mv "${file_list}" "${dest_dir}/" ; then
echo "无法移动 ${file_list} 到 ${dest_dir}" >&2
exit "${E_BAD_MOVE}"
fi
# 或者
mv "${file_list}" "${dest_dir}/"
if [[ "$?" -ne 0 ]]; then # 命令执行成功正常退出码为0。 -ne 不等于
echo "无法移动 ${file_list} 到 ${dest_dir}" >&2
exit "${E_BAD_MOVE}"
fi
终于抄完作业了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。