格式

缩进

Tip

缩进两个空格,没有制表符。

在代码块之间请使用空行以提升可读性。缩进为两个空格。无论你做什么,请不要使用制表符。对于已有文件,保持已有的缩进格式。

行的长度和长字符串

Tip

行的最大长度为80个字符。

如果你必须写长度超过80个字符的字符串,如果可能的话,尽量使用here document或者嵌入的换行符。长度超过80个字符的文字串且不能被合理地分割,这是正常的。但强烈建议找到一个方法使其变短。

  1. # DO use 'here document's
  2. cat <<END;
  3. I am an exceptionally long
  4. string.
  5. END
  6.  
  7. # Embedded newlines are ok too
  8. long_string="I am an exceptionally
  9. long string."

管道

Tip

如果一行容不下整个管道操作,那么请将整个管道操作分割成每行一个管段。

如果一行容得下整个管道操作,那么请将整个管道操作写在同一行。

否则,应该将整个管道操作分割成每行一个管段,管道操作的下一部分应该将管道符放在新行并且缩进2个空格。这适用于使用管道符’|’的合并命令链以及使用’||’和’&&’的逻辑运算链。

  1. # All fits on one line
  2. command1 | command2
  3.  
  4. # Long commands
  5. command1 \
  6. | command2 \
  7. | command3 \
  8. | command4

循环

Tip

请将 ; do , ; thenwhile , for , if 放在同一行。

shell中的循环略有不同,但是我们遵循跟声明函数时的大括号相同的原则。也就是说, ; do , ; then 应该和 if/for/while 放在同一行。 else 应该单独一行,结束语句应该单独一行并且跟开始语句垂直对齐。

例如:

  1. for dir in ${dirs_to_cleanup}; do
  2. if [[ -d "${dir}/${ORACLE_SID}" ]]; then
  3. log_date "Cleaning up old files in ${dir}/${ORACLE_SID}"
  4. rm "${dir}/${ORACLE_SID}/"*
  5. if [[ "$?" -ne 0 ]]; then
  6. error_message
  7. fi
  8. else
  9. mkdir -p "${dir}/${ORACLE_SID}"
  10. if [[ "$?" -ne 0 ]]; then
  11. error_message
  12. fi
  13. fi
  14. done

case语句

Tip

  • 通过2个空格缩进可选项。
  • 在同一行可选项的模式右圆括号之后和结束符 ;; 之前各需要一个空格。
  • 长可选项或者多命令可选项应该被拆分成多行,模式、操作和结束符 ;; 在不同的行。

匹配表达式比 caseesac 缩进一级。多行操作要再缩进一级。一般情况下,不需要引用匹配表达式。模式表达式前面不应该出现左括号。避免使用 ;&;;& 符号。

  1. case "${expression}" in
  2. a)
  3. variable="..."
  4. some_command "${variable}" "${other_expr}" ...
  5. ;;
  6. absolute)
  7. actions="relative"
  8. another_command "${actions}" "${other_expr}" ...
  9. ;;
  10. *)
  11. error "Unexpected expression '${expression}'"
  12. ;;
  13. esac

只要整个表达式可读,简单的命令可以跟模式和 ;; 写在同一行。这通常适用于单字母选项的处理。当单行容不下操作时,请将模式单独放一行,然后是操作,最后结束符 ;; 也单独一行。当操作在同一行时,模式的右括号之后和结束符 ;; 之前请使用一个空格分隔。

  1. verbose='false'
  2. aflag=''
  3. bflag=''
  4. files=''
  5. while getopts 'abf:v' flag; do
  6. case "${flag}" in
  7. a) aflag='true' ;;
  8. b) bflag='true' ;;
  9. f) files="${OPTARG}" ;;
  10. v) verbose='true' ;;
  11. *) error "Unexpected option ${flag}" ;;
  12. esac
  13. done

变量扩展

Tip

按优先级顺序:保持跟你所发现的一致;引用你的变量;推荐用 ${var} 而不是 $var ,详细解释如下。

这些仅仅是指南,因为作为强制规定似乎饱受争议。

以下按照优先顺序列出。

  • 与现存代码中你所发现的保持一致。
  • 引用变量参阅下面一节,引用。
  • 除非绝对必要或者为了避免深深的困惑,否则不要用大括号将单个字符的shell特殊变量或定位变量括起来。推荐将其他所有变量用大括号括起来。
  1. # Section of recommended cases.
  2.  
  3. # Preferred style for 'special' variables:
  4. echo "Positional: $1" "$5" "$3"
  5. echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ ..."
  6.  
  7. # Braces necessary:
  8. echo "many parameters: ${10}"
  9.  
  10. # Braces avoiding confusion:
  11. # Output is "a0b0c0"
  12. set -- a b c
  13. echo "${1}0${2}0${3}0"
  14.  
  15. # Preferred style for other variables:
  16. echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}"
  17. while read f; do
  18. echo "file=${f}"
  19. done < <(ls -l /tmp)
  20.  
  21. # Section of discouraged cases
  22.  
  23. # Unquoted vars, unbraced vars, brace-quoted single letter
  24. # shell specials.
  25. echo a=$avar "b=$bvar" "PID=${$}" "${1}"
  26.  
  27. # Confusing use: this is expanded as "${1}0${2}0${3}0",
  28. # not "${10}${20}${30}
  29. set -- a b c
  30. echo "$10$20$30"

引用

Tip

  • 除非需要小心不带引用的扩展,否则总是引用包含变量、命令替换符、空格或shell元字符的字符串。
  • 推荐引用是单词的字符串(而不是命令选项或者路径名)。
  • 千万不要引用整数。
  • 注意 [[ 中模式匹配的引用规则。
  • 请使用 $@ 除非你有特殊原因需要使用 $*
  1. # 'Single' quotes indicate that no substitution is desired.
  2. # "Double" quotes indicate that substitution is required/tolerated.
  3.  
  4. # Simple examples
  5. # "quote command substitutions"
  6. flag="$(some_command and its args "$@" 'quoted separately')"
  7.  
  8. # "quote variables"
  9. echo "${flag}"
  10.  
  11. # "never quote literal integers"
  12. value=32
  13. # "quote command substitutions", even when you expect integers
  14. number="$(generate_number)"
  15.  
  16. # "prefer quoting words", not compulsory
  17. readonly USE_INTEGER='true'
  18.  
  19. # "quote shell meta characters"
  20. echo 'Hello stranger, and well met. Earn lots of $$$'
  21. echo "Process $$: Done making \$\$\$."
  22.  
  23. # "command options or path names"
  24. # ($1 is assumed to contain a value here)
  25. grep -li Hugo /dev/null "$1"
  26.  
  27. # Less simple examples
  28. # "quote variables, unless proven false": ccs might be empty
  29. git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"}
  30.  
  31. # Positional parameter precautions: $1 might be unset
  32. # Single quotes leave regex as-is.
  33. grep -cP '([Ss]pecial|\|?characters*)$' ${1:+"$1"}
  34.  
  35. # For passing on arguments,
  36. # "$@" is right almost everytime, and
  37. # $* is wrong almost everytime:
  38. #
  39. # * $* and $@ will split on spaces, clobbering up arguments
  40. # that contain spaces and dropping empty strings;
  41. # * "$@" will retain arguments as-is, so no args
  42. # provided will result in no args being passed on;
  43. # This is in most cases what you want to use for passing
  44. # on arguments.
  45. # * "$*" expands to one argument, with all args joined
  46. # by (usually) spaces,
  47. # so no args provided will result in one empty string
  48. # being passed on.
  49. # (Consult 'man bash' for the nit-grits ;-)
  50.  
  51. set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$*"; echo "$#, $@")
  52. set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$@"; echo "$#, $@")

原文: https://zh-google-styleguide.readthedocs.io/en/latest/google-shell-styleguide/formatting/