Shell中的特殊位置参数变量全文收录

一、位置参数变量的作用

一句话概括:我们要从命令行、函数或者脚本执行等处传递参数时,就需要在shell脚本中使用位置参数变量

二、Shell中的特殊未知参数变量有哪些

1)$0
作用:获取当前执行的shell脚本的脚本名字(如果脚本中包含了路径,那获取的就是脚本路径)
2)$n
作用:获取当前执行的shell脚本的第n个参数(n=1..9),当n=0时,则就是$0获取脚本名,当n≥10,则必须使用{},例如:${10},当n有多个时,则参数之间用空格隔开
3)$#
作用:获取当前执行的shell脚本后面接的参数的总个数
4)$
作用:获取当前执行的shell脚本后面所有的参数,如果给
$
加上双引号,即*"$"时,则表示把所有的参数视为不同的单个**字符串,相当于:"$1 $2 $3"

5)$@
作用:获取当前执行的shell脚本后面所有的参数,如果给$@加上双引号,即"$@"时,则表示把所有的参数视为不同的独立字符串,相当于:"$1" "$2" "$3",这种方式是把多参数传递给其他程序的最佳方式,因为它会保留所有的内嵌在每个参数里的任何空白

特殊说明:当*"$""$@"**都加双引号时是有区别的,当两者都不加双引号时,是完全没区别的

6)$?
作用:获取执行上一个指令的执行状态返回值(0为成功,非0为失败,⭐️这个变量非常的常用⭐️
7)$$
作用:获取当前执行的shell脚本的进程号(即PID),不太常用,了解即可
8)$!
作用:获取上一个在后台工作的进程的进程号,不太常用,了解即可
9)$_
获取在此之前执行的命令或脚本的最后的一个参数,类似于我们使用的快捷键“esc+.”,因为是在非交互模式下,所以使用$_,一般常用,了解即可

三、分别距离说明9个特殊位置参数变量

1)$0
[root@dabiaoge ~]# vim abc.sh
[root@dabiaoge ~]# cat abc.sh
echo $0
[root@dabiaoge ~]# sh abc.sh
abc.sh
[root@dabiaoge ~]# sh /root/abc.sh
/root/abc.sh
如果想单独获取脚本名或者路径,则配合下面的小命令:
[root@dabiaoge ~]# basename /root/abc.sh
abc.sh
关于basename的详细讲解,请浏览地址:
http://blog.51cto.com/zpf666/2335218
[root@dabiaoge ~]# dirname /root/abc.sh
/root
关于dirname的详细讲解,请浏览地址:
http://blog.51cto.com/zpf666/2335223
说明:若不带路径执行脚本,则输出的结果就是脚本名;
如果使用全路径执行脚本,那么输出的结果就是全路径+脚本名
2)$n
[root@dabiaoge ~]# vim abc.sh
[root@dabiaoge ~]# cat abc.sh
echo $1
[root@dabiaoge ~]# sh abc.sh dabiaoge
dabiaoge
[root@dabiaoge ~]# vim abc.sh
[root@dabiaoge ~]# cat abc.sh
echo $1 $2
[root@dabiaoge ~]# sh abc.sh dabiaoge dabiaoge2
dabiaoge dabiaoge2
[root@dabiaoge ~]# vim abc.sh
[root@dabiaoge ~]# cat abc.sh
echo $1 $2 $3
[root@dabiaoge ~]# sh abc.sh "dabiaoge dabiaoge2" dabiaoge3 dabiaoge4
dabiaoge dabiaoge2 dabiaoge3 dabiaoge4
说明:⑴参数与参数之间用空格隔开
⑵加引号括起来的参数会作为一个字符串看待
[root@dabiaoge ~]# echo \${1..15} > num.sh
[root@dabiaoge ~]# cat num.sh
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[root@dabiaoge ~]# vim num.sh
[root@dabiaoge ~]# cat num.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
[root@dabiaoge ~]# sh num.sh {a..z}
a b c d e f g h i a0 a1 a2 a3 a4 a5
为什么会出现a0 a1 a2 a3 a4 a5,而不是字母呢?这是因为前面提过的,当n≥10,则必须使用{},例如:${10},请看下面:
[root@dabiaoge ~]# vim num.sh
[root@dabiaoge ~]# cat num.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
[root@dabiaoge ~]# sh num.sh {a..z}
a b c d e f g h i j k l m n o
说明:⑴当n≥10,则必须使用{}
⑵生产环境下规范的写法是"$1" "$2" "$3",就是$n用双引号括起来
3)$#
[root@dabiaoge ~]# vim abc.sh
[root@dabiaoge ~]# cat abc.sh
echo $#
[root@dabiaoge ~]# sh abc.sh {a..z}
26
条件表达式判断语句的写法(例子):
[root@dabiaoge ~]# vim tt1.sh
[root@dabiaoge ~]# cat tt1.sh

#!/bin/bash                             
[ $# -ne 2 ] && {                  //“-ne”是不等于的意思,“-eq”是等于的意思
echo "必须两个参数"
exit 1
}
echo dabiaoge_nb

[root@dabiaoge ~]# sh tt1.sh dabiaoge1
必须两个参数
[root@dabiaoge ~]# sh tt1.sh dabiaoge1 dabiaoge2
dabiaoge_nb
if判断语句的写法(例子):
[root@dabiaoge ~]# vim tt2.sh
[root@dabiaoge ~]# cat tt2.sh

#!/bin/bash
if [ $# -ne 2 ]
then
echo "用法:/bin/sh $0 参数1 参数2"             //注意此处的$0,打印脚本名
exit 1
fi
echo $1 $2

[root@dabiaoge ~]# sh tt2.sh dabiaoge1
用法:/bin/sh tt2.sh 参数1 参数2
[root@dabiaoge ~]# sh tt2.sh dabiaoge1 dabiaoge2
dabiaoge1 dabiaoge2br/>4)**$***和**$@**
举例说明的材料:
[root@dabiaoge ~]# set -- "I am" big biaoge //“set --”表示清除所有的参数变量,重新设置后面的参数变量
[root@dabiaoge ~]# echo $#
3
[root@dabiaoge ~]# echo $1
I am
[root@dabiaoge ~]# echo $2
big
[root@dabiaoge ~]# echo $3
biaoge
测试①:两者都不带双引号
普通测试:
[root@dabiaoge ~]# echo $
I am big biaoge
[root@dabiaoge ~]# echo $@
I am big biaoge
使用for循环测试:
[root@dabiaoge ~]# for i in $
;do echo $i;done
I
am
big
biaoge
[root@dabiaoge ~]# for i in $@;do echo $i;done
I
am
big
biaoge
[root@dabiaoge ~]#
说明:两次测试结果两者完全一样,甚至“I am”这第一个参数也给分开了。
测试②:两者都带双引号
普通测试:
[root@dabiaoge ~]# echo "$*"
I am big biaoge
[root@dabiaoge ~]# echo "$@"
I am big biaoge
使用for循环测试:

[root@dabiaoge ~]# for i in "$*";do echo $i;done
I am big biaoge
[root@dabiaoge ~]# for i in "$@";do echo $i;done
I am
big
biaoge
[root@dabiaoge ~]# for i;do echo $i;done
I am
big
biaoge

说明:当普通测试的时候还是完全没区别,一旦使用for循环测试,就出现了不同之处。*即:在for循环+双引号的情况下,$和$@是不一样的
去掉"in 变量列表",相当于有引号的in "$@"。
5)
$?
[root@dabiaoge ~]# pwd
/root
[root@dabiaoge ~]# echo $?
0
[root@dabiaoge ~]# ls /dabiaoge
ls: cannot access /dabiaoge: No such file or directory
[root@dabiaoge ~]# echo $?
2
说明:在生产环境下,$?返回值的用法:
①判断命令、脚本或函数等程序是否执行成功
②若在
脚本中调用执行“exit 数字”,则会返回这个数字给“$?”变量
③如果是在
函数里面,则通过“return 数字”把这个数字以函数返回值的形式传给“$?”
6)
$$**
[root@dabiaoge ~]# vim test_pid.sh
[root@dabiaoge ~]# cat test_pid.sh
echo $$ > /tmp/abc.pid
sleep 300
[root@dabiaoge ~]# ps -ef | grep test_pid | grep -v grep
[root@dabiaoge ~]# sh test_pid.sh &
[1] 13107
[root@dabiaoge ~]# ps -ef | grep test_pid | grep -v grep
root 13107 3977 0 22:01 pts/0 00:00:00 sh test_pid.sh
[root@dabiaoge ~]# cat /tmp/abc.pid
13107
说明:通过ps看到的脚本的进程号13107与/tmp/abc.pid里面的数字是一样的,这就是靠$$传参过来的值。
一般运用场景:有时执行定时任务脚本的频率比较快,并不知道上一个脚本是否真的执行完毕,但是,业务要求同一时刻只能有一个同样的脚本在运行,此时就需要利用$$来获取上一次运行的脚本进程号,当程序重新运行时,根据获取的进程号,清理掉上一次的进程。举例脚本如下:
[root@dabiaoge ~]# cat pid.sh

#!/bin/bash
pidpath=/tmp/ceshi.pid
#如果pid文件存在,则执行then后面的命令
if [ -f "$pidpath" ]
then
#杀掉与前一个进程号对应的进程
kill $(cat $pidpath) > /dev/null 2&>1
rm -rf $pidpath
fi
echo $$ > $pidpath
sleep 300

[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
[root@dabiaoge ~]# sh pid.sh &
[1] 13580
[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
root 13580 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[root@dabiaoge ~]# sh pid.sh &
[2] 13592
[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
root 13592 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[1]- Terminated sh pid.sh
[root@dabiaoge ~]# sh pid.sh &
[3] 13603
[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
root 13603 3977 0 22:13 pts/0 00:00:00 sh pid.sh
[2]- Terminated sh pid.sh
7)$!
[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
[root@dabiaoge ~]# sh pid.sh &
[1] 13806
[root@dabiaoge ~]# echo $!
13806
[root@dabiaoge ~]# ps -ef | grep pid.sh | grep -v grep
root 13806 3977 0 22:18 pts/0 00:00:00 sh pid.sh
说明:$!的功能类似于$$,只不过作用是获取上一次执行脚本的pid
8)$_
[root@dabiaoge ~]# systemctl restart nginx.service
[root@dabiaoge ~]# systemctl restart nginx.service
[root@dabiaoge ~]# echo $_
nginx.service
说明:$_就是上一条命令的最后一个参数值。

猜你喜欢

转载自blog.51cto.com/zpf666/2335281