Shell特殊位置变量

Shell中存在一些特殊且重要的变量,如下

  • $0    获取当前执行Shell脚本的文件名字,如果执行脚本时候加了路径,那就包含脚本路径跟脚本名字一起输出
  • $n    获取当前执行Shell交本的第n个参数,n=1..9,n>9,后面参数变量就需要用大括号,如:${10},以空格分隔
  • $#    获取当前执行Shell脚本接了多少个参数(总计)
  • $*    获取当前执行Shell脚本所有传参的参数
  • $@    获取当前执行Shell脚本所有传参的参数($*和$@详解见例子)
 1 [root@ king tmp]# cat t.sh
 2 if [ $# -ne 2 ]             #如果执行脚本传参的个数不为2,
 3   then
 4     echo "USAGE:/bin/sh $0 arg1 arg2"    #则给用户提示正确用法,此处的$0,打印脚本名字及路径。
 5     exit 1                #若不满足要求,则退出脚本,返回值为1。
 6 fi
 7 echo $1 $2                  #若参数满足要求,则打印$1和$2获取到的传参的字符串。
 8 [root@ king tmp]# sh t.sh            #若不加参数执行脚本,则直接给出提示。
 9 USAGE:/bin/sh t.sh arg1 arg2           #t.sh就是脚本中$0获取的值。
10 [root@ king tmp]# sh t.sh hello world
11 hello world                        #若参数满足要求,则打印$1和$2获取的字符串,即hello和world。

$0,$n,$#,这几个就不多说了,因为太好理解了,下面我们来一起学习一下$*和$@的区别吧。

我们可以利用set 来设置位置参数Age of loss

 1 [root@king tmp]# set -- "This is" Age of loss.  #“--”表示清除所有的参数变量,重新设置后面的参数变量。
 2 [root@king tmp]#echo $#    #输出参数的个数。
 3 3                 #共三个参数。
 4 [root@king tmp]# echo $1    #打印第一个参数值。
 5 This is
 6 [root@king tmp]# echo $2    #打印第二个参数值。
 7 Age
 8 [root@king tmp]# echo $3    #打印第三个参数值。
 9 of
10 [root@king tmp]# echo $4    #打印第四个参数值。
11 loss.
12 #测试$*和$@,注意,此时不带双引号:
13 [root@king tmp]# echo $*    #打印$*。
14 This is Age of loss.
15 [root@king tmp]# echo $@     #打印$@。
16 This is Age of loss.
17 [root@king tmp]# for i in $*; do echo $i; done           #使用for循环输出$*测试。
18 This          #($*)不加双引号,因此会输出所有参数,然后第一个参数"This is"也拆开输出了。
19 is
20 Age
21 of
22 loss
23 [root@king tmp]# for i in $@; do echo $i; done    #使用for循环输出$@测试。
24 This              #($@)不加双引号,因此会输出所有参数,然后第一个参数"This is"也拆开输出了。
25 is
26 Age
27 of
28 loss
29 #测试"$*"和"$@",注意,此时带有双引号:
30 [root@king tmp]# echo "$*"
31 This is Age of loss.
32 [root@king tmp]# echo "$@"
33 This is Age of loss.
34 [root@king tmp]# for i in "$*"; do echo $i; done
35 This is Age of loss.   #在有双引号的情况下"$*",参数里引号中的内容当作一个参数输出了!
36 [root@king tmp]# for i in "$@"; do echo $i; done
37 This is   #在有双引号的情况下,每个参数均以独立的内容输出,且有双引号算一个参数。
38 Age
39 of
40 loss
41 #这才真正符合我们传入的参数需求,set -- "This is" Age of loss.

Shell特殊状态变量

Shell特殊状态变量

  • $?     获取执行上一个指令的执行状态返回值(0成功,非0为失败)
  • $$      获取当前执行Shell脚本的进程号(PID)
  • $!       获取上一个在后台工作的进程的进程号(PID)
  • $_      获取在此之前执行的命令或脚本的最后一个参数

$?特殊变量,根据返回值来判断备份成功于否,例子

1 [root@king tmp]# cd /etc/
2 [root@king  etc]# tar zcf /opt/services.tar.gz ./services     #打包备份
3 [root@king  etc]#  echo  $?   #检查备份后的,返回0表示打包成功,
4 0

我们可以查看一下NFS网络文件共享系统/etc/init.d/rpcbind脚本中的50-73行吧,学习一下$?使用,

 1 [root@king scripts]# sed -n '63,73p' /etc/init.d/rpcbind        #sed  -n 打印文件指定行、
 2 stop() {
 3         echo -n $"Stopping $prog: "
 4      killproc $prog                      #这是停止rpcbind的命令。
 5         RETVAL=$?                     #将上述命令的返回值“$? ”赋值给RETVAL变量,用于后面的判断。
 6         echo
 7         [ $RETVAL -eq 0 ]&&{        #这里就是判断,如果返回值为0,则执行下面的指令。
 8                 rm -f /var/lock/subsys/$prog
 9                 rm -f /var/run/rpcbind*
10         }
11         return $RETVAL       #如果返回值不等于0,则跳过判断,直接作为返回值传给执行stop函数的脚本。
12 }

$?返回值的用法总结:

  1. 判断命令,脚本或者函数等程序是否执行成功
  2. 若在脚本中调用执行“exit 数字”,则会返回这个数字给“$?”变量
  3. 如果是在函数里,则通过“return 数字”,把这个数字以函数返回值的形式传给“$?”

Shell特殊扩展变量

Shell特殊位置变量

我们可以man bash 命令,然后搜索”Parameter Expansion”来查找相关的内容帮助

  • ${parameter:word}       如果parameter的变量值为空或没赋值,则返回word字符串并代替变量的值(变量没定义,返回备用的值,防止变量为空或没定义报错)
  • ${parameter:=word}      如果parameter的变量值为空或没赋值,。。。同上,(变量没定义为防止出错,找的备胎变量)
  • ${parameter:?word}      如果parameter的变量值为空或者没赋值,word字符串就作为标准错误输出,否则出书变量的值(捕捉由于变量未定义导致的错误,并退出)
  • ${parameter:+word}      若果parameter的变量值为空或者未赋值,则什么都不做,否则word字符串将代替变量的值。

${parameter:-word}用法距离:没有赋值的情况

1 [root@king tmp]# echo $test      #变量未设置,所以输出时为空。
2 [root@king tmp]# result=${test:-UNSET}       #<==若test没值,则返回UNSET。
3 [root@king tmp]# echo $result    #打印result变量,返回UNSET,因为test没有赋值。
4 UNSET
5 [root@king tmp]# echo ${test}    #注意,此时打印test变量还是为空。
结论:对于${test:-UNSET},当test变量没值时,就返回变量结尾设置的UNSET字符串。
赋值的情况
1 [root@king tmp]# test=hello  #赋值hello字符串。
2 [root@king tmp]# echo $test
3 hello
4 [root@king tmp]# result=${test:-UNSET}              
5 [root@king tmp]# echo $result  #因为test已赋值,因此,打印result就输出了test的值hello,而不是原来的UNSET。
6 hello
7 [root@king tmp]# result=${test-UNSET}               #定义时忽略了冒号。
8 [root@king tmp]# echo $result
9 hello                                               #打印结果和带冒号时没有变化。

${parameter:=word}和${parameter:-word}差不多,理解都是一样的,变量为赋值就把备胎给变量。。。

${parameter:?word}变量为赋值或空,就将该字符串(word)作为标准错误输出。

 1 [root@king tmp]# echo ${key:? not defined}   #key变量没有定义,因此,把“not defined”作为标准错误输出。
 2 -bash: key: not defined       #错误提示,只不过是事先定义好的错误输出。
 3 [root@king tmp]# echo ${key? not defined}     #去掉冒号定义,并输出,结果一致。
 4 -bash: key: not defined
 5 [root@king tmp]# key=5 #<==给变量赋值1。
 6 [root@king tmp]# echo ${key:? not defined}    #因为key有值了,所以,打印key的值。
 7 5
 8 [root@king tmp]# echo ${key? not defined}     #去掉冒号定义,并输出,结果一致。
 9 5
10 [root@king tmp]# unset key     #取消key的定义。
11 [root@king tmp]# echo ${key:? not defined}
12 -bash: key: not defined           #又打印错误提示了。

${parameter:+word}变量为空或没赋值,什么都不做,否则用word字符串替换变量的值

1 [root@king tmp]# key=${value:+word}      #value变量未定义。
2 [root@king tmp]# echo $key        #因为value变量未定义,所以打印key变量为空。
3 [root@king tmp]# value=25           #value变量赋值为25。
4 [root@king tmp]# key=${value:+word} #注意,这里一定要重新定义key。
5 [root@king tmp]# echo $key
6  word                           #因为value变量有值,所以打印key变量输出为“:+ ”后面的内容。

 

版权声明:本文为liang-io原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/liang-io/p/9841490.html