shell脚本的易犯错误
1. for i in x y z : 这句是以空格作为分隔符的,当我们的$n中包含空格的话,就会有错误
如 for i in `ls *.mp3` ,这句 ls *.mp3执行后如果有空格就gg了
直接 for i in *.mp3 就好了
2. cp $file $target :当$file中有空格时就会出错
正确: cp "$file" "$target"
但是$file为-开头的话,会被当作命令行选线处理,就像 cp -ap $1 $2中的-ap一样
完全的方法:用for循环
for i in ./*.mp3;do cp "$i" /$target;done
小结:在shell脚本中遇到$n需要注意空格问题,一般来说,变量要用""做处理
总的来说,在命令如cd 直接操作之前,进行过换算的如$或者``,都需要注意空格问题
3. [ "$foo" = "bar" ]:当$foo以-开头时,会报错。
[[能正确处理空格,空白,带横线等问题
正确:[[ $foo = bar ]],当然 [ bar = "foo" ]也可以
4. cd `dirname "$f"`:当路径中含有空格时,就会出错,处理方式类型为上面进行的总结
正确:cd "`dirname "$f"`" 在shell中""是进行的由内往外的匹配,这点与c语言中的就近匹配是不一样的
5. [ bar = "$foo" && foo = "$bar" ]:在学习shell中,我们把test与[]对比学习的,这两者是一致的,所以把该式子变换为test bar = "$foo" && foo = "$bar"这其实是两个式子了
正确的 [ bar = "$foo" -a foo = "$bar" ] 或者[[ bar = "$foo" && foo = "$bar" ]] 或者 [ bar = "$foo"]&&[ foo = "$bar" ]
6. [[ $f > 7 ]]:很遗憾呢,[[不能用作数字的比较,之前都没注意过,因为都不用
(($f>7))或我经常用的[ "$f" -gt 7 ],不过先要判断$f是数字,不然也会出错呢。-----${string##*[0-9]}是否为空,为空就说明$string为纯数字
[[email protected] ~]# f=123456
[[email protected] ~]# echo $f
123456
[[email protected] ~]# echo ${f##*[0-9]}
[[email protected] ~]# echo ${f#*[0-9]}
23456
7. grep foo file|while read line;do ((count++));done
执行之后count的值并没有变化,因为啊 | 管道就是一个shell子进程,子shell中的变量是无法传递出来的
[[email protected] ~]# grep s /etc/passwd|while read line;do ((count++));done
[[email protected] ~]# echo $count
[[email protected] ~]# grep s /etc/passwd|while read line;do ((count++));echo $count|tr "\n" " ";done
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
8. if [grep s /etc/passwd]:if后面接一个判断语句,它会将if与then之间的所有命令返回值当作判断条件
但[]是一个语法,他并不是if的一部分,二者无必然联系
所以上面的应该写成 if grep s /etc/passwd >/dev/null;then ..
9. if [[ a = b ]&&[ c = d ]];then:理由同上 应改为 if [ a = b ]&&[ c =d ];then
10. sed ‘s/foo/bar/g‘ file >file :不能从一个文件读,然后直接就修改,但我记得sort有参数-o可以
11. echo $foo
MSG="please enter a file form like *.zip"
echo $MSG时,会出现*.zip匹配A.zip的情况,正确的做法是 echo "$MSG"
12. foo = bar 或 $foo=bar: 变量赋值时,正确为foo=bar 不要空格,这不是c语言
13. cat >>file<<eof也可以用 cat <<eof 此处是cat,不要搞成echo了
14. cd /foo;rm *:很危险的操作,因为/foo的foo可能不存在,那此句就会在/目录下删除
正确:cd /foo && rm * ;根据cd的返回值执行多条语句可以这样cd /foo ||exit 1;cd .. rm ....
15. [ bar == "$foo" ]:学习的时候,就说的很明白。[]是不支持除=以外的比较符的,且=也只用在string的比较上
16. for i in {1..10};do something &;done报错,此处直接去掉; 因为&可以起到分割的作用
[[email protected] ~]# for i in {1..10};do echo 1 &;done
-bash: syntax error near unexpected token `;
17. cmd1 && cmd2 || cmd3:我很喜欢用,但当cmd2返回一个非0值,那么cmd3也是会被执行的
正确的是: if cmd1 ;then cmd2;else cmd3;fi
18. 在命令行 echo "hello!" 会报!的错误且不能\进行转义,但在shell脚本中没有这个错误
ifconfig 可以在命令行把ip给单独提取出来,但在shell脚本中是提取不出来的-----很蛋疼吧
19. for i in $*:错误点为 $*自己为一个string,当命令行参数有空格时,就会产生错误,
正确的做法 for i in "[email protected]" --------取命令行传参优先用这个就好了
20. function foo()在bash中没有问题,但在其他shell中有可能出错,所以不要把function和括号一起使用
直接foo()就好了