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为纯数字

[root@Scott ~]# f=123456

[root@Scott ~]# echo $f

123456

[root@Scott ~]# echo ${f##*[0-9]} 


[root@Scott ~]# echo ${f#*[0-9]} 

23456


7. grep foo file|while read line;do ((count++));done

执行之后count的值并没有变化,因为啊 | 管道就是一个shell子进程,子shell中的变量是无法传递出来的

[root@Scott ~]# grep s /etc/passwd|while read line;do ((count++));done                

[root@Scott ~]# echo $count


[root@Scott ~]# 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报错,此处直接去掉;  因为&可以起到分割的作用

[root@Scott ~]# 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 "$@" --------取命令行传参优先用这个就好了


20. function foo()在bash中没有问题,但在其他shell中有可能出错,所以不要把function和括号一起使用

直接foo()就好了