做为运维人员,经常使用linux的都知道,在linux下面,很多命令、关键字,看起来长的很像,但实际应用起来就能够发现有时候还是有区别的,当然不仔细的人或许你是永远也不会明白,到底什么时候该使什么招。今天做为菜鸟的我,就给大家简单的分享几个,不全之处,希望大家留言指出,本博主随时更新,以方便大家紧急查阅。

菜鸟的发现:
       一、$var_name与"$var_name"
       二、"$*"与"$@"
       三、[  ]与[[  ]]

 

一、$var_name与"$var_name"
大多数情况下,$var_name与"$var_name"没什么区别,但是就因如此,所以我们写脚本的时候,经常会遇到一些另人费解的报错,很多人就感觉我写的没错啊,语法没错,命令拼写也没有问题,就不知道究竟错在哪里。殊不知就是这个引号让你绞尽脑汁,如果你能看到我这个小菜鸟的博文,或许你也彻底明白并记住它了。
接下来,我们用一个简短的示例演示一下
[root@centos7 test]# cat test.sh     测试环境展示($var-name不带引号)

#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 21:07:38
#Description:

if [ $1 = start ];then   这脚本咋一看,相当简单,语法、拼写各方面也都没问题吧
  echo start
elif [ $1 = stop ];then   好的,接下来,就让我们带上参数来亲测一下
  echo stop
elif [ $1 = restart ];then
  echo restart
else
  echo "Unknown parameter"
fi
[root@centos7 test]# test.sh start  带上正确的参数一点问题也没有
start
[root@centos7 test]# test.sh rest
Unknown parameter
[root@centos7 test]# test.sh   可为什么没带参数,就报了一大串的错误了,没带参数,不也是属于else分支吗
./test.sh: line 8: [: =: unary operator expected
./test.sh: line 10: [: =: unary operator expected
./test.sh: line 12: [: =: unary operator expected
Unknown parameter
[root@centos7 test]#

仔细看看,前三个判断的分支都报错了,错误提示大概意思是期待一元表达式,那我们就要思考一下,接下来,我们给$1包上一个引号再来看看

[root@centos7 test]# vim test.sh
[root@centos7 test]# cat test.sh   测试环境展示("$var-name"带引号)

#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 21:07:38
#Description:

if [ "$1" = start ];then
  echo start
elif [ "$1" = stop ];then
  echo stop
elif [ "$1" = restart ];then
  echo restart
else
  echo "Unknown parameter"
fi
[root@centos7 test]# test.sh stop
stop
[root@centos7 test]# test.sh restart
restart
[root@centos7 test]# test.sh hello    
Unknown parameter
[root@centos7 test]# test.sh    头痛的问题消失了,即使不带参数,也不会报错,正常走到了else分支
Unknown parameter
[root@centos7 test]#

这回应该能够明白这个大多数情况都一样的$var_name与"$var_name"之间一个引号的威力了吧。所以小菜还是建议大家养成一个良好的编程习惯,不惯它俩大多数情况是不是效果等同,我们不要去偷那个懒,只要是引用变量的时候,我们就把那个该死的引号给带上不就得了,免得头痛了还不知何故。

 

二、"$*"与"$@"
接下来我们就再来一个也和这个引号有一点关系的"$*"与"$@",写过脚本的都知道,脚本里面涉及到了位置变量,$*与$@都表示变量列表,可谁知道用小菜建议的以不变应万变的规律这回就掉大了。

测试环境:
[root@centos7 test]# cat script1.sh
#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 15:18:57
#Description:

script2.sh "$*"        特殊变量(参数列表)加引号调用的
echo ==============================
script2.sh "$@"        特殊变量(参数列表)加引号调用的
[root@centos7 test]# cat script2.sh
#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 15:12:52
#Description:

echo "The first parameter is:$1"
echo "The second parameter is:$2"
echo "The third parameter is:$3"
echo "All parameters is:$@"

[root@centos7 test]# script1.sh a ab abc  $*和$@用引号时的执行效果
The first parameter is:a ab abc
The second parameter is:    "$*"表示的是把整个列表当成一个参数$1
The third parameter is:     所以$2和$3都为空值
All parameters is:a ab abc
==============================
The first parameter is:a
The second parameter is:ab     "$@"表示的还是分散的整个列表
The third parameter is:abc     所以$2和$3都能正常得到赋值
All parameters is:a ab abc
[root@centos7 test]#
正常加了引号,这回也掉大了,两个都是表示参数列表的变量,调用的同样参数还有区别了,仔细查阅相关资料,终于发现$*和$@确实是双胞胎,但它们还是有区别的:
"$*"(用双引号时): 传递给脚本的所有参数,全部参数合为一个字符串
"$@"(用双引号时): 传递给脚本的所有参数,每个参数为独立字符串

接下来我们看一下不用引号时的示例:
[root@centos7 test]# cat script1.sh
#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 15:18:57
#Description:

script2.sh $*
echo ==============================
script2.sh $@
[root@centos7 test]# cat script2.sh
#!/bin/bash

#Author:wangjun
#Version:1.0
#Create time:2016-08-14 15:12:52
#Description:

echo "The first parameter is:$1"
echo "The second parameter is:$2"
echo "The third parameter is:$3"
echo "All parameters is:$@"

[root@centos7 test]# script1.sh a ab abc  $*和$@不用引号时的执行效果
The first parameter is:a
The second parameter is:ab    因为$*和$@不用引号时,两个表示的都是分散的整个列表
The third parameter is:abc   所以$2和$3都能正常得到赋值
All parameters is:a ab abc
==============================
The first parameter is:a
The second parameter is:ab
The third parameter is:abc
All parameters is:a ab abc
[root@centos7 test]#

$*和$@不用引号时:两个表示的都是分散的整个列表(也即每个参数都是独立的字符串),能看得出来,这次没用引号反而还不会出岔子。所以只能得出一个结论,任何事务都不是绝对的,一定是有前提或环境的。当然对于我们使用linux系统的运维人员来说,这些知识你是必须掌握的,否则出了这些情况你真会抓狂的。

 

三、[  ]与[[  ]]
大多数情况下,[  ]与[[  ]]也都差不多,那么今天小菜再你来看一幅伤脑筋的画卷
[root@centos7 test]# A=good
[root@centos7 test]# echo $A
good
[root@centos7 test]# [ -n $A ] && echo "A is nonespace" || echo "A is space" 
A is nonespace                 测试字符串是否非空,没加引号调用变量,也没报错

[root@centos7 test]# [ -z $A ] && echo "A is space" || echo "A is nonespace" 
A is nonespace                  走运了(这是属于大多数情况之列的)

[root@centos7 test]# [ $A =~ go ] && echo "Matching" || echo "Not matching"  
-bash: [: =~: binary operator expected    再来一个用右边的模式去匹配左边,错误报告来了

Not matching
[root@centos7 test]# [ "$A" =~ go ] && echo "Matching" || echo "Not matching" 
-bash: [: =~: binary operator expected    使法宝——加一个引号,结果失效了

Not matching
[root@centos7 test]# [[ "$A" =~ go ]] && echo "Matching" || echo "Not matching" 
Matching                           双中括号的大救星从天而降,妖怪终于压到了五指山下      

[root@centos7 test]# [[ $A =~ god ]] && echo "Matching" || echo "Not matching"  
Not matching            此时发现摘掉它的紧箍咒——双引号,它也无力翻身

[root@centos7 test]# [[ $A =~ go ]] && echo "Matching" || echo "Not matching"
Matching
[root@centos7 test]#

通过这一次的测试我们又可以发现,[  ]与[[  ]]也是孪生兄弟,但有时候它们的性格也还是有点小区别的,所以我们在用的时候,同样需要把好关了。
好的,今天的分享也就至此为此,不全之处,希望读者及时留言补充。