这是我写BASH程序的招式。这里本没有什么新的内容,但是从我的经验来看,人们爱滥用BASH。他们忽略了计算机科学,而从他们的程序中创造的是“大泥球”(译注:指架构不清晰的软件系统)。 在此我告诉你方法,以保护你的程序免于障碍,并保持代码的整洁。
不可改变的全局变量- 尽量少用全局变量
- 以大写命名
- 只读声明
- 用全局变量来代替隐晦的$0,$1等
在我的程序中常使用的全局变量:
1 2 3 | readonly PROGNAME=$(basename $0)
readonly PROGDIR=$(readlink -m $(dirname $0))
readonly ARGS="$@"
|
一切皆是局部的所有变量都应为局部的。 1 2 3 4 5 6 7 | change_owner_of_file() {
local filename=$1
local user=$2
local group=$3
chown $user:$group $filename
}
|
1 2 3 4 5 6 7 8 9 10 11 | change_owner_of_files() {
local user=$1; shift
local group=$1; shift
local files=$@
local i
for i in $files
do
chown $user:$group $i
done
}
|
- 自注释(self documenting)的参数
- 通常作为循环用的变量i,把它声明为局部变量是很重要的。
- 局部变量不作用于全局域。
1 2 | kfir@goofy ~ $ local a
bash: local: can only be used in a function
|
main()- 有助于保持所有变量的局部性
- 直观的函数式编程
代码中唯一的全局命令是:main
1 2 3 4 5 6 7 8 9 10 | main() {
local files="/tmp/a /tmp/b"
local i
for i in $files
do
change_owner_of_file kfir users $i
done
}
main
|
一切皆是函数- 不可变的全局变量声明 - main()函数 1 2 3 | main() {
local files=$(ls /tmp | grep pid | grep -v daemon)
}
|
1 2 3 4 5 6 7 8 9 10 11 | temporary_files() {
local dir=$1
ls $dir \
| grep pid \
| grep -v daemon
}
main() {
local files=$(temporary_files /tmp)
}
|
1 2 3 4 5 6 7 8 9 10 11 12 | test_temporary_files() {
local dir=/tmp
touch $dir/a-pid1232.tmp
touch $dir/a-pid1232-daemon.tmp
returns "$dir/a-pid1232.tmp" temporary_files $dir
touch $dir/b-pid1534.tmp
returns "$dir/a-pid1232.tmp $dir/b-pid1534.tmp" temporary_files $dir
}
|
如你所见,这个测试不关心main()。 调试函数只调试一小段代码,使用set-x和set+x,会只对被set -x和set +x包含的当前代码打印调试信息。 1 2 3 4 5 6 7 8 9 | temporary_files() {
local dir=$1
set -x
ls $dir \
| grep pid \
| grep -v daemon
set +x
}
|
打印函数名和它的参数: 1 2 3 4 5 6 7 8 | temporary_files() {
echo $FUNCNAME $@
local dir=$1
ls $dir \
| grep pid \
| grep -v daemon
}
|
调用函数: 会打印到标准输出:
|