当前文章接着Bash编程陷阱一写下来。

文章目录

24. for arg in $*

bash使用$*或者$@来承担脚本的所有入参,但用for遍历的时候需要注意

for arg in "$@"
# 或者更简单的写法
for arg

这里的$@需要添加上"",此处的"$@"相当于"$1","$2","$3",而非"$1 $2 $3"

加引号的目的自然是预防空格,如果$1存在空格,那么就多出一个参数

25. function foo()

function的写法并不在所有的shell解释器中兼容。请使用

foo() {
  ...
}

26. echo "~"

~符号只有被引号括起来的时候才能转换为home目录的绝对地址,在""中只能打印出~符号,在特殊的日志输出里面需要注意。

示例:

tmp/oenhan $ echo ~/
/home/oenhan/
tmp/oenhan $ echo "~/"
~/

27. local varname=$(command)

一般情况下,在其后使用ret=$?获取command的返回值,但事实上获取是local定义的返回值,应该如下写法

local varname
varname=$(command)
rc=$?

28. export foo=~/bar

~并不在所有shell解释器中自动转换为home的绝对路径,不过bash里面是支持的。

29. sed 's/$foo/good bye/'

单引号里面不会转换$foo变量,可以使用双引号,当然,双引号内考虑的事情更多了

强迫症患者可能感觉不太美观,可以换成如下样子

sed 's/'$foo'/good bye/'

看起来有点乱,其实是正常的。

30. tr [A-Z] [a-z]

这样写法有三个问题,1,[a-z]被认为是通配符,如果当前没有单字母命名的文件,执行应该是OK的,否则就会对文件操作了。2.tr转换字符将[转换为对应的[,没有意义,直接去掉。3,A-Z在不同的语言环境中不一定会代表26个 ASCII 字母,使用前需要设定语言环境

LC_COLLATE=C tr A-Z a-z

不建议上面这个写法,推荐man手册中的写法

tr '[:upper:]' '[:lower:]'

31. ps ax | grep gedit

靠名称判断进程不靠谱,具体不解释

32. printf "$foo"

当foo中有特殊字符作为printf参数存在的时候,直接使用printf是有害的

需要在printf后面加上打印格式,示例:

$ foo='a%sdn'
$ printf $foo
ad
$ printf %s $foo
a%sdn

33. for i in {1..$n}

此处的$n不会展开,{x..y}的展开的限制条件是:1) 整数或者单个字符; 2)两者要是同一个类型。{1..$n}不满足以上条件。具体参考GNU手册

具体实现推荐直接使用for循环搞定

34. if [[ $foo = $bar ]]

[[]]里面不加引号会做模式匹配,$bar如果*,则结果永远为真。

35. if [[ $foo =~ 'some RE' ]]

加''后正则表达式就失效了,和34结果相反。

36. [ -n $foo ] or [ -z $foo ]

仍然是字符串没有加引号,不为空有空格或者为空,都会有语法错误。

37. [[ -e "$broken_symlink" ]] returns 1 even though $broken_symlink exists

-e判断一个文件是否存在,但在判断软链接的时候,实际返回值是链接文件是否存在的结果;即链接的目标文件不存在,但软链接仍然存在,此时仍然返回失败。符号链接的判断建议用-L处理。

38. ed file <<<"g/d{0,3}/s//e/g" fails

ed使用的正则表达式,不支持0的出现次数

39. expr sub-string fails for "match"

match是expr的关键字,使用的时候需要加+号

word=match
expr + "$word" : ".(.*)"
atch

expr古董般难用的命令,应该被抛弃了

40. On UTF-8 and Byte-Order Marks (BOM)

BOM在脚本执行的时候和win的换行符一样可能有问题。

41. content=$(<file)

所有内容只有1行,换行符丢掉了

42. for file in ./* ; do if [[ $file != *.* ]]

file的字符串会带上./,在匹配的时候就会有问题。

43. somecmd 2>&1 >>logfile

解释器对位置敏感,此处相当于somecmd >> logfile;somecmd 2 >&1


Bash编程陷阱二来自于OenHan

链接为:https://oenhan.com/bash-pitfalls-2

发表回复