Bash是Unix系统和Linux系统的一种命令行环境,也是目前绝大多数Linux发行版的默认Shell。Shell不仅是一个程序,也是一个命令解释器,可以支持变量、条件判断、循环等语法。我们在平时的工作中也都会使用Shell这个工具,编写脚本,方便的使用操作系统提供的功能,自动化的完成定义的任务。
这篇文章就说明如何编写更规范的Shell脚本,大家可以查看、收藏,以指导后续编写Shell脚本更规范、更易读。
一、美学
1、使用Tab键还是空格键?
Tab键
2、分号
在命令行中结尾无需使用分号,在脚本中也不用使用分号。
# wrong name='dave'; echo "hello $name"; #right name='dave' echo "hello $name"
3、函数
不要使用关键字function创建函数。所有函数中创建的变量都应该声明为局部变量。
# wrong function foo { i=foo # this is now global, wrong } # right foo() { local i=foo # this is local, preferred }
4、代码块声明
then应与if放在同一行,do应与while放在同一行。
# wrong if true then ... fi # also wrong, though admittedly looks kinda cool true && { ... } # right if true; then ... fi
5、间距
不要超过两个连续的换行符(即不超过一行空行)。
6、注释
注释没有明确的代码风格。除非你重写或者更新注释内容,否则不要因为美观的因素去改动它。
二、Bash主义
1、条件测试
使用[[...]] 进行条件测试,而不是[...] 或 test ...
# wrong test -d /etc # also wrong [ -d /etc ] # correct [[ -d /etc ]]
2、队列
使用bash的内部命令生成队列
n=10 # wrong for f in $(seq 1 5); do ... done # wrong for f in $(seq 1 "$n"); do ... done # right for f in {1..5}; do ... done # right for ((i = 0; i < n; i++)); do ... done
3、命令赋值
使用$(...)进行命令赋值
foo=`date` # wrong foo=$(date) # right
4、数学/整数操作
使用((...)) 和 $((...))
a=5 b=4 # wrong if [[ $a -gt $b ]]; then ... fi # right if ((a > b)); then ... fi
5、参数扩展
使用参数扩展好于使用外部命令,如echo、sed、awk等。
name='bahamas10' # wrong prog=$(basename "$0") nonumbers=$(echo "$name" | sed -e 's/[0-9]//g') # right prog=${0##*/} nonumbers=${name//[0-9]/}
6、列出文件
不要使用ls,而使用bash内置函数来循环文件
# very wrong, potentially unsafe for f in $(ls); do ... done # right for f in *; do ... done
7、数组和列表
只要有可能,尽量使用 bash 数组来代替使用空格(或是换行符、制表符等)分隔的字符串。
# wrong modules='json httpserver jshint' for module in $modules; do npm install -g "$module" done # right modules=(json httpserver jshint) for module in "${modules[@]}"; do npm install -g "$module" done
8、内置读取
只要有可能,使用 bash 内置的 read 避免调用外部命令。
fqdn='computer1.daveeddy.com' IFS=. read hostname domain tld <<< "$fqdn" echo "$hostname is in $domain.$tld" # => "computer1 is in daveeddy.com"
三、外部命令
在编写bash时,并且使用给你的所有强大工具和bash的内建命令时,你会发现很少需要调用外部命令。比如:awk、sed、grep等。
不要在不需要的时候使用cat,如果程序支持从标准输入读取,使用bash重定向传递数据。
# wrong cat file | grep foo # right grep foo < file # also right grep foo file
四、风格
1、引号
当字符串需要变量扩展或命令替换插值的时候使用双引号,其它时候使用单引号。
# right foo='Hello World' bar="You are $USER" # wrong foo="hello world" # possibly wrong, depending on intent bar='You are $USER'
2、变量声明
避免大写的变量名,除非有一个很好的理由使用他们。不要使用 let 或 readonly 创建变量。declare 应该只用于关联数组。在函数中,应始终使用 local 声明变量。
# wrong declare -i foo=5 let foo++ readonly bar='something' FOOBAR=baz # right i=5 ((i++)) bar='something' foobar=baz
3、shebang
Bash 不总是位于 /bin/bash,因此尽量这样来写这一行:
#!/usr/bin/env bash
4、错误检查
举个例子,cd 不总是工作。请务必检查 cd(或类似的命令)任何可能的错误,如果错误存在就退出或将错误抛出。
# wrong cd /some/path # 可能会失败 rm file # 如果 cd 失败我在哪?我删除了什么? # right cd /some/path || exit rm file
5、set -e
不要设置 errexit。如同在 C 语言中,有时你想要得到一个错误,或是你期望什么执行失败,并不意味着你想要退出程序。
6、eval
永远不要使用