总结工作中写bash脚本过程中遇到的一些问题,总结出的最佳实践。
0x01 if
if 支持判断字符串和数字。字符串添加x
字符,为了防止变量为空时出现告警。
if [ "x$1" == "x0" ]; then
echo "equal '0'"
fi
if [ "$1" -eq 0 ]; then
echo "equal 0"
fi
0x02 子shell
- 子shell中export的环境变量,父进程不能感知。
- 子shell通过()触发。如
$(ls /path)
,或者是一对反引号包住的。`ls`
。推荐第1种方式,可以多层嵌套。 - 重定向一块代码的标准输出或者标准错误可以用
{}
包住。
{
ls /
} > /dev/null
0x03 基本运算
用 a=$(($a+1))
0x04 有用的选项
set -o pipefail
打开管道失败抛错,当管道中有任何一个命令失败时,整个命令的退出码就非0。
set -x
打开调试,脚本执行时,会把执行的每一行打印出来,方便调试定位出错的位置。
0x05 路径展开
正常情况下*
会自动被bash展开。如果不小心把*
包括在了""
或者''
中,就不会展开了。
# ulin @ linmac in ~/Documents/tmp [20:41:29]
$ ls 1*
1.txt 11.txt
# ulin @ linmac in ~/Documents/tmp [20:41:31]
$ ls "1*"
ls: 1*: No such file or directory
0x06 内置变量
$?
是紧挨着的上一个命令的退出码。如果需要引用,要用变量先保存下来。echo一个日志就可能修改这个内置变量。$@
与$*
都是指脚本执行时传入的参数列表。"$@"
会原样保留传入的参数,而"$*"
会把引号去掉。
function print()
{
echo $1
echo $2
echo $3
}
echo '$@'
print "$@"
echo '$*'
print "$*"
输出
$@
1 2
3 4
$*
1 2 3 4
0x07 局部变量声明
function
中用local
限制变量的作用域,避免污染全局变量。
0x08 以变量形式存在的命令中有空格时
直接执行,会提示命令找不到。
$cmd
可以用bash -c 去执行,就可以规避了。
bash -c $cmd
0x09 字符串替换
参考自bash manual
类型 | 功能 |
---|---|
# prefix移除 ${parameter#word} ${parameter##word} |
移除开头的字符串。##会匹配最长的。 |
% %% suffix移除 |
移除结尾的 |
/ // 替换 |
支持通配符展开。 |
#!/bin/bash
echo "prefix trim"
a="namename233233"
echo "short trim: ${a#*e}"
echo "long trim: ${a##*e}"
echo "suffix trim"
echo "short trim: ${a%2*}"
echo "long trim: ${a%%2*}"
echo "substitute"
echo "sub 1: ${a/name/hello}"
echo "sub all: ${a//name/hello}"
0x0a 正则匹配
比使用grep更优雅。
a="/aaaa/bbb"
[[ $a =~ 'aaaa' ]] && echo "matched"