Bash Style Guide

Bash Style Guide

前言

在 Github 上看到有同学整理的 《 Bash Style Guide》,受教良多,翻译一份做备忘。

原作者的介绍

这篇 Guide 的目标是为了提高 Bash 脚本的安全和可读性, 基于这篇 wiki.

特别是这一页: BashGuide/Practices.

如果 Guide 中没有提及的,默认参考原 Wiki.

Bash 之美

  • TAB / 空格 优先使用 TAB 做分隔符.
  • 分号 既然敲命令行时不用分号, 那在 Bash 脚本里也不要用啦. # 错误的示范 name='dave'; echo "hello $name"; # 正确的示范 name='dave' echo "hello $name"
  • 函数 不要使用function关键字, 所有函数作用域内的变量应该声明为local. # 错误的示范 function foo { i=foo } # 正确的示范 foo() { local i=foo }
  • 代码段落 ifthen在同一行, dowhile在同一行. # 错误的示范 if true then ... fi # 虽然看上去挺酷, 但是还是一个错误的示范 true && { ... } # 正确的示范 if true; then ... fi
  • 空行 不要连续两个空行
  • 注释 没有太多风格建议, 但不要因为审美而修改其他小伙伴的注释, 除非你在重写或者更新这块代码~

Bash 内建命令

这是一篇 Bash 编码风格建议, 这意味着, 给出的建议更倾向于内建的 Bash 命令或者关键字, 而非外部命令或者sh(1)这样的句法.

  • test(1) 做条件判断时, 使用 [[ ... ]] 而非 [ .. ] 或者 test ... # 错误的示范 test -d /etc [ -d /etc ] # 正确的示范 [[ -d /etc ]] 更多可以参考 http://mywiki.wooledge.org/BashFAQ/031
  • 序列 优先使用 Bash 的内建命令 n=10 # 错误的示范 for f in $(seq 1 5); do ... done # 错误的示范 for f in $(seq 1 "$n"); do ... done # 正确的示范 for f in {1..5}; do ... done # 正确的示范 for ((i = 0; i < n; i++)); do ... done
  • 命令替换 使用 $(...) 做命令替换 # 错误的示范 foo=`date` # 正确的示范 foo=$(date)
  • 数学运算 使用 ((...))$((...)). 千万不要使用let. a=5 b=4 # 错误的示范 if [[ $a -gt $b ]]; then ... fi # 正确的示范 if ((a > b)); then ... fi
  • 参数扩展 参考parameter expansion, 优先使用内建命令, 而非echo, sed, awk这些. name='bahamas10' # 错误的示范 prog=$(basename "$0") nonumbers=$(echo "$name" | sed -e 's/[0-9]//g') # 正确的示范 prog=${0###*/} nonumbers=${name//[0-9]/}
  • 遍历文件 优先使用内建命令, 不要使用parse ls(1) # 大错特错, 不安全 for f in $(ls); do ... done # 正确的示范 for f in *; do ... done
  • 可执行文件的路径 简而言之, 你不应该知道这个路径; 如果你在尝试寻找可执行文件的全路径, 那你应该重新思考下软件设计. 更多可以参考这里.
  • 数组和列表 尽可能使用 Bash 的内建数组, 而不是一串被空格分开的 string # 错误的示范 modules='json httpserver jshint' for module in $modules; do npm install -g "$module" done # 正确的示范 modules=(json httpserver jshint) for module in "${modules[@]}"; do npm install -g "$module" done
  • 使用read 尽可能的使用内建命令read, 避免 fork # 正确的示范 fqdn='computer1.daveeddy.com' IFS=. read hostname domain tld <<< "$fqdn" echo "$hostname is in $domain.$tld" # => "computer1 is in daveeddy.com" # 另一个按行读文件的正确示范 while read line; do ... done < file_to_read

外部命令

  • GNU 工具 世界不仅仅运行在 GNU 或者 Linux 上, 当 fork 外部命令时, 例如awk, sed, grep等等, 为了保持可移植性, 尽可能避免 GNU 的特殊选项. 当你使用 Bash 的强大内建命令写脚本时, 你会发现几乎用不到这些外部命令.
  • uuoc" class="anchor" href="#uuoc">UUOC 不需要时别用cat(1), 如果程序支持从 stdin 读入, 使用重定向传递数据. # 错误的示范 cat file | grep foo # 正确的示范 grep foo < file grep foo file 优先使用内建的命令行工具读文件, 而不是从 stdin 读入.

编码风格

  • 引号 当需要变量扩展或者命令解释替换时使用双引号, 其他情况下使用单引号. # 正确的示范 foo='Hello World' bar="You are $USER" # 错误的示范 bar='You are $USER' 变量如果会被分割(包含空格, TAB或者新行), 必须要加引号, 否则可以不加. foo='hello world' if [[ -n $foo ]]; then # 不需要加引号 echo "$foo" # 需要加引号 fi bar=$foo # 不需要加引号 唯一的例外是变量明确不会被分割(生命周期有保证), 例如, basher 中有段代码: printf_date_supported=false if printf '%()T' &>/dev/null; then printf_date_supported=true fi # 这里可以不需要引号 if $printf_date_supported; then ... fi 同理, $, $?, $#, 也不需要引号, 因为他们不会包含空格, TAB或者新行. 如果不确定, 那还是都把引号加上吧, 个人更推荐这样, 简单又安全, quote all expansions.
  • 变量声明 避免大写变量名, 除非确实有必要. 不要使用let或者readonly创建变量名. declare应该用在关联数组中. 在函数中尽量使用local. # 错误的示例 declare -i foo=5 let foo++ readonly bar='something' FOOBAR=baz # 正确的示例 i=5 ((i++)) bar='something' foobar=baz
  • 环境声明 (原E文标题是 shebang, "家当"的意思, 可是为什么我想起了萨满的蛇棒……) Bash 不一定都在 /bin/bash, 所以使用下面的方式: #!/usr/bin/env bash
  • 错误检查 举个例子, cd不一定成功, 使用 exit 或者 break 来保证检查可能出现的错误. # 错误的示范 cd /some/path # 可能失败 rm file # 如果 cd 失败, 还删不删? # 正确的示范 cd /some/path || exit rm file
  • set -e 不要设置errexit, 和 C 一样, 一些时候会预期发生错误或者失败, 但是并不希望程序退出. 这里有详细的解释.
  • eval 永远不要用!

错误示范

Bash Pitfalls

License

MIT Licencse

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Jerry的SAP技术分享

JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载

Java程序员面试系列-什么是Java Marker Interface(标记接口)

792
来自专栏技术栈大杂烩

Linux:终端提示符 (prompt) 不如期生效原因

先来简单介绍下, prompt是什么鬼? 顾名思义就是提示符的意思, 看起来和我们遥远, 但实际上只要是每个接触shell的童鞋, 都有看到, 那就是我们在输命...

1405
来自专栏Google Dart

Flutter Widget框架之旅 顶

Flutter小部件采用现代反应式框架构建,从React中获得灵感。 中心思想是你从小部件中构建你的UI。 小组件描述了他们的视图在给定其当前配置和状态时应该看...

6152
来自专栏赵康的专栏

在Atom中配置Python开发环境

当然,这里有很多很棒的文本编辑器。例如Sublime Text, Brackets, Atom。我一直都是Atom的粉丝,因为它是完全免费的,而且它有很多可用的...

1K13
来自专栏程序员同行者

django rest framework通用view

官方文档:http://www.django-rest-framework.org/ drf为我们提供强大的通用view的功能,本博客对这些view进行简要的...

1092
来自专栏逍遥剑客的游戏开发

Tiled源码分析(三): Undo/Redo实现

3237
来自专栏我和我大前端的故事

我练习项目眼中的 vue

因为毕业设计开始了 vue 的学习之路,曾写过一些入门的 vue 小白学习文章系列(2018 我所了解的 Vue 知识大全(一))。如今已经工作半年了,这一次想...

3142
来自专栏JackieZheng

AngularJS入门心得1——directive和controller如何通信

  粗略地翻了一遍《JavaScript DOM编程艺术》,就以为可以接过AngularJS的一招半式,一个星期过去了,我发现自己还是Too Young,Too...

2376
来自专栏后端云

python,NFV项目开发--vim

vim是python开发最常用的编辑工具之一,本文不是介绍vim的,而是结合python进行实际项目开发,说一说vim在python开发中的心得。

2313
来自专栏web前端教室

9.6,*少芳-学习笔记【web前端零基础课】

在学习一些js内容后,完成了一部分网站首页的动作设置(搜索栏、侧边栏、轮播图),对js代码进行了封装,重新整理了js文件。(index.js\ma...

1257

扫码关注云+社区

领取腾讯云代金券