Shell编程规约


 ____                      _          _ _
| __ )  __ _ ___  ___  ___| |__   ___| | |
|  _ \ / _` / __|/ _ \/ __| '_ \ / _ \ | |
| |_) | (_| \__ \  __/\__ \ | | |  __/ | |
|____/ \__,_|___/\___||___/_| |_|\___|_|_|

首条规约

本Shell规约规定

【强制】Linux 工具的使用不必死记硬背,不必死记硬背,不必死记硬背,即查即用即可。

运行方式

本Shell规约规定

【强制】脚本均以`.sh`结尾
正例:BaseLog.sh、init.sh
说明:以`.sh`结尾,使人可以一目了然知道该文件是脚本文件,而且用的解析器是sh或bash

【强制】脚本执行明确指定具体解析器
正例: #!/bin/bash 、#!/usr/bin/bash、#!/usr/bin/env bash
说明: 参考首行规约,这样可以不用每个文件都单独赋予可执行权限

【强制】脚本执行要到脚本所在目录下执行

命名风格

本Shell规约规定

【强制】脚本中变量、函数、文件的命名均不能以数字、下划线、$开头,也不能以下划线或者$结尾
反例: _name / __name / $name / name_ / name$ / 5name
说明: $作为Shell语言的取值符号,其他命名约束参考Java规约。

【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
正例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。
说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式 也要避免采用。

【强制】参数名、局部变量都统一使用 lowerCamelCase 风格,必须遵从 驼峰形式。
正例: localValue / errMsg / userName

【推荐】使用下划线分割函数命名,都统一使用 lowerCamelCase 风格,必须遵从 驼峰形式。
正例:getUserName() / log_info() / map_add()
说明: 纯用下划线会使得命名很长,纯用驼峰又无法将函数聚类
get_user_english_name()  vs getUserEnglishName()
log_info() vs logInfo()
map_add() vs mapAdd()
log_info "xxx" 在调用的时候类比于Java 的 log.info("xxx")

【强制】文件名 UpperCamelCase 风格,首字母大写的驼峰形式
正例:BaseLog.sh / BaseString.sh
说明:类比Java的类,我们把相同功能的函数抽象到一个脚本文件中,留待后续其他脚本引用。随着我们写的脚本日渐增多
我们很有必要分门别类的将它们聚集到一个文本文件中,一是方便后续查阅,而是方便后续调用

【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT 反例:MAX_COUNT

【推荐】文件夹名字统一大写或者统一小写,推荐大写
【强制】文件名以 .sh 结尾
【强制】使用两个空格进行缩进,不适用tab缩进
【推荐】不在一行的时候使用 `\` 进行换行,使用 `\` 换行的原则是整齐美观

关于首行

本Shell规约规定

【推荐】推荐使用 `#!/usr/bin/env bash` 作为 shebang
说明: 提高脚本的可以执性

关于数组

本Shell规约规定

【强制】传递数组使用 "${list[*]}" 形式
【强制】接收数组使用 array=($*) 形式
正例:
# @return the number of elements in this list
function list_size(){
  local array=($1);local size=${\#array[*]}
  echo "${size}"
}
size=$(list_size "${list[*]}")
assertEquals "${size}" "2"

关于变量

本shell规约规定

【推荐】不要定义与环境变量重名的局部变量,会改变环境变量的值,进而影响后续脚本的执行。
【推荐】如果要打破上一个推荐,修改后及时修改回来。例如 IFS 代表分隔符的情况。
【强制】变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。
【强制】变量取值用 "${}", 使用 {} 包裹,给所有变量加上花括号,防止产生歧义
【强制】变量取值用 "${}", 使用 "" 包裹,防止分词
【强制】若需要将调用的函数的返回结果赋值给local变量,使用 $(),不推荐使用 ``
【推荐】能缩小变量作用域的就缩小变量的作用域,也就是能用local的就用local修饰
【强制】认定为常量的必须用readonly修饰,相当于 Java 中的final
【推荐】删除变量能不用就不用,一般没什么应用场景

关于函数

本Shell规约规定

【强制】函数需有注释标识该函数的用途、入参变量、函数的返回值类型
【强制】函数的注释 `#` 顶格写, 井号后面紧跟一个空格,对于该格式的要求是为了最后生成函数的帮助文档是用的(markdown语法),然后是注释的内容,注释尽量简短且在一行,最后跟的是函数的类型。
【强制】函数内注释 `#` 与缩进格式对整齐
【强制】变量的注释紧跟在变量的后面,不推荐换行写注释
【强制】在函数内部首先使用有意义的变量名接受参数,然后在使用这些变量进行操作,禁止直接操作$1,$2等,除非这些变量只用一次
【推荐】不推荐使用return方式返回,推荐使用echo方式返回结果
【推荐】返回结果类型是Boolean类型,也就是说函数的功能是起判断作用,返回结果是真或者假的时候使用才显示 return 返回结果

关于注释

本Shell规约规定

【强制】认定为常函数的必须用readonly修饰,相当于 Java 中的final。
【推荐】使用关键字 `function` 显示定义的函数为 public 的函数,可以供 外部脚本以 `sh 脚本 函数 函数入参` 的形式调用,可以认为成Java当中的public的方法
【推荐】未使用关键字 `function` 显示定义的函数为 private 的函数, 仅供本脚本内部调用,可以认为成Java中的私有方法,注意这种private是人为规定的,并不是Shell的语法,不推荐以 `sh 脚本 函数 函数入参` 的形式调用,注意是不推荐而不是不能。
【强制】将函数分门别类保存在不同的脚本中
【推荐】使用source的方式引入另一个脚本中的函数,不推荐使用`脚本 函数名 函数参数`的形式调用

说明:本Shell规约这样做的目的就在于使脚本具有一定的封装性,看到 function 修饰的就知道这个函数能被外部调用, 没有被修饰的函数就仅供内部调用。你就知道如果你修改的函数的影响范围. 如果是 被function 修饰的函数,修改后可能影响到外部调用他的脚本, 而修改未被function修饰的函数的时候,仅仅影响本文件中其他函数。

关于分支

HEAD_KEYWORD parameters; BODY_BEGIN
  BODY_COMMANDS
BODY_END

本Shell规约规定

【强制】将HEAD_KEYWORD和初始化命令或者参数放在第一行;
【强制】将BODY_BEGIN同样放在第一行;
【强制】复合命令中的BODY部分以2个空格缩进;
【强制】BODY_END部分独立一行放在最后;
【推荐】parameters部分test表达式变量取值都用""包裹;
【推荐】parameters部分test表达式统一使用=等符号, 在明确是数字的时候可以使用 -eq等参数;
【强制】if\while\until 后面的判断 使用 双中括号`[[]]`

关于数学计算

本Shell规约规定

【推荐】明确知道变量是整数,计算使用$(())包裹计算,(())内对变量的操作不用$取值
正确 a=$((1+1))
反例 a=$(($a++))
【推荐】复杂计算使用bc计算器,前提是得安装bc计算器命令

单元测试

【推荐】建议写单元测试

未完待续,明天再写


评论
  目录