Shell 参数含义 $0、$1、$2、${n}、$#、$@、$*、$?、 $_、$!、$$
编写 Linux bash shell 脚本时,经常会用到 $0、$1、$2、${n}、$#、$@、$*、$?、 $_、$!、$$ 等参数,下面具体说明这些参数的含义。
假设执行 ./test.sh a b c 这样一个命令,则可以使用下面的参数来获取一些值:
示例:./test.sh a b c 或者 sh test.sh a b c
$0 对应 "./test.sh" 这个值。如果执行的是 ./work/test.sh, 则对应 ./work/test.sh 这个值,而不是只返回文件名本身的部分。
$1 会获取到第1个参数 a,即 $1 对应传给脚本的第一个参数。
$2 会获取到第2个参数 b,即 $2 对应传给脚本的第二个参数。
$3 会获取到第3个参数 c,即 $3 对应传给脚本的第三个参数。
$4、$5、$n 等参数的含义依此类推,且从第10个位置参数开始,必须使用花括号括起来,如:${10}
$# 会获取到参数的个数 3,对应传入脚本的参数个数,即(a b c)共3个参数,统计的参数不包括 $0(shell 脚本本身)。
$@ 会获取到 "a" "b" "c",也就是所有参数的列表,数组格式 以 "参数1" "参数2" … "参数n" 形式保存所有参数,不包括 $0。这是将参数传递给其它程序的最佳方式,因为它会保留所有内嵌在每个参数里的任何空格分隔
$* 也会获取到 "a" "b" "c", 其值和 $@ 相同,是一整个字符串 以 "参数1 参数2 … " 形式保存所有参数,不包括 $0。
但 "$*" 和 "$@" 有所不同:"$@" 会得到一个字符串参数数组,而 "$*" 把所有参数合并成一个字符串。
$? 可以获取到执行 ./test.sh a b c 命令后的返回值。在执行一个前台命令后,可以立即用 $? 获取到该命令的返回值。
该命令可以是系统自身的命令,可以是 shell 脚本,也可以是自定义的 bash 函数,返回 0 表示成功;其它值,则是失败。
$_ 在此之前执行的命令或脚本的最后一个参数
$! 上一个命令的PID
$$:获取当前的shell进程号PID
简单总结
$# 表示位置参数的数量
$* 表示所有位置参数的内容
$? 表示命令执行后返回的状态 (执行成功 返回0 执行不成功 返回非0)
$$ 表示当前进程的进程号 希望打开一个进程后不再打开另一个(/proc/<PID>)
$! 表示后台运行的最后一个进程号
$0 表示当前的进程名
"$*" 和 "$@" 参数值
假设有一个 shell_test_param.sh 脚本,内容如下:
vim shell_test_param.sh
#!/bin/bash # # mimvp.com 2010.12.22 echo "--- test string $* ---" for arg in "$*"; do echo "arg *** : " $arg done echo "--- test array $@ ---" for arg in "$@"; do echo "arg @@@ : " $arg done
这个脚本分别遍历 "$*" 和 "$@" 扩展后的内容,并打印出来。
执行 sh shell_test_param.sh,结果如下:
$ sh shell_test_param.sh I love mimvp.com --- test string I love mimvp.com --- arg *** : I love mimvp.com --- test array I love mimvp.com --- arg @@@ : I arg @@@ : love arg @@@ : mimvp.com
可以看到
"$*" 只产生一个字符串,for 循环只遍历一次。
"$@" 产生了多个字符串组成的数组,for 循环遍历多次,是一个字符串参数数组。
注意:
如果传入的参数多于 9 个,则不能使用 $10 来引用第 10 个参数,而是要用 ${10} 来引用。即,需要用大括号{}把大于 9 的数字括起来。
例如,${10} 表示获取第 10 个参数的值,写为 $10 获取不到第 10 个参数的值。
实际上,$10 相当于 ${1}0,也就是先获取 $1 的值,后面再跟上 0,如果 $1 的值是 "first",则 $10 的值是 "first0"。
示例:
vim shell_test_param10.sh
#!/bin/bash # # mimvp.com in 2010.12.12 echo $0 echo $1 echo $2 echo $3 echo $4 echo $5 echo $6 echo $7 echo $8 echo $9 echo $10 echo ${10} echo $11 echo ${11}
运行结果:
$ sh shell_test_param10.sh a b c d e f g h i j k l m n shell_test_param10.sh a b c d e f g h i a0 j a1 k
可见,$0 表示shell脚本 ;$10 表示 $1 = ${1}0 = a0,${10} 才是j ;同理 $11 与 ${11}
查看 man bash 里面对位置参数(positional parameters)的说明如下:
Positional Parameters
A positional parameter is a parameter denoted by one or more digits, other than the single digit 0.
Positional parameters are assigned from the shell's arguments when it is invoked, and may be reassigned using the set builtin command. Positional parameters may not be assigned to with assignment statements. The positional parameters are temporarily replaced when a shell function is executed.
When a positional parameter consisting of more than a single digit is expanded, it must be enclosed in braces.
即,最后一句提到,当位置参数由多位数字组成时,需要用大括号 {} 把多位数字括起来。
$# 参数个数
在 bash 中,可以使用 $# 来获取传入的命令行或者传入函数的参数个数。
要注意的是,$# 统计的参数个数不包括脚本自身名称或者函数名称。
例如,执行 ./a.sh a b,则 $# 是参数个数 2(即 a b ,不包含shell脚本 ./a.sh),因此不是 3。
查看 man bash 的说明如下:
Special Parameters
# Expands to the number of positional parameters in decimal.
可以看到,$# 实际上是扩展为位置参数(positional parameters)的个数,统计的参数不包括 $0。
$? 执行的返回值
1、当执行系统自身的命令时,$? 对应这个命令的返回值,0为成功,非0为失败
$ echo "I love mimvp.com" I love mimvp.com $ echo $? 0 $ echo ${mimvp.com} -bash: ${mimvp.com}: bad substitution $ echo $? 1 r$ $ sh shell_test_param.sh I love mimvp.com --- test string I love mimvp.com --- arg *** : I love mimvp.com --- test array I love mimvp.com --- arg @@@ : I arg @@@ : love arg @@@ : mimvp.com $ echo $? 0
如上,执行 echo、sh xxx.sh 都是成功的,$? 返回值都是 0
执行 echo ${mimvp.com} 提示错误,未定义变量值,返回错误,$? 返回值是 1 (非0值)
2、当执行 shell 脚本时,$? 对应该脚本调用 exit 命令返回的值
如果没有主动调用 exit 命令,默认返回为 0
vim shell_test_return.sh
#!/bin/bash # # mimvp.com in 2010.12.12 args_str=$* args_arr=$@ args_num=$# if (( ${args_num} > 0 )); then echo "args_num: ${args_num}" exit 0 else echo "no args" exit 1 fi
执行结果:
$ sh shell_test_return.sh I love mimvp.com args_num: 3 $ echo $? 0 $ sh shell_test_return.sh no args $ echo $? 1
代码说明:
有参数传入(参数个数大于0),成功返回0;无参数传入,失败返回1
3、当执行自定义的 bash 函数时,$? 对应该函数调用 return 命令返回的值
如果没有主动调用 return 命令,默认返回为 0
vim shell_test_return.sh
#!/bin/bash # # mimvp.com in 2010.12.12 args_str=$* args_arr=$@ args_num=$# function test_return() { if (( ${args_num} > 0 )); then echo "args_num: ${args_num}" return 0 else echo "no args" return 1 fi } test_return echo $?
执行结果:
$ sh shell_test_return.sh I love mimvp.com args_num: 3 $ sh shell_test_return.sh I love mimvp.com args_num: 3 0 $ sh shell_test_return.sh no args 1
代码说明:
有参数传入(参数个数大于0),成功 return 返回0;无参数传入,失败return 返回1
$_、$!、$$
$_ 在此之前执行的命令或脚本的最后一个参数
$! 上一个命令的PID
$$:获取当前的shell进程号PID
示例代码:
vim shell_test_return.sh
#!/bin/bash # # mimvp.com in 2010.12.12 args_str="$*" args_arr="$@" args_num="$#" function test_return() { if (( ${args_num} > 0 )); then echo "args_num: ${args_num}" echo "args_str: ${args_str}" echo "args_arr: ${args_arr}" # for arg in "$*" for arg in ${args_str} do echo "arg *** ${arg}" done for arg in ${args_arr} do echo "arg @@@ ${arg}" done return 0 else echo "no args" return 1 fi } echo "------" echo '$_' "$_" echo '$!' "$!" echo '$$' "$$" echo '$_' "$_" test_return a b c echo '$_' "$_" echo $? echo '$_' "$_" echo '$!' "$!" echo '$$' "$$" echo '$_' "$_"
执行结果:
$ sh shell_test_return.sh I love mimvp.com ------ $_ ------ $! $$ 19164 $_ 19164 args_num: 3 args_str: I love mimvp.com args_arr: I love mimvp.com arg *** I arg *** love arg *** mimvp.com arg @@@ I arg @@@ love arg @@@ mimvp.com $_ c 0 $_ 0 $! $$ 19164 $_ 19164
代码说明:
$_ 在此之前执行的命令或脚本的最后一个参数,例如:test_return a b c 的最后一个参数 $_ c , $$ 19164 的最后一个参数 $_ 19164,
$! 上一个命令的PID,似乎没效果,总是空
$$:获取当前的shell进程号PID,例如:$$ 19164
上面,需要重点说明一下,for arg in ${args_str} 和 for arg in ${args_arr} 返回的都是数组,原因是 args_str 和 args_arr 是空格隔开的字符串,类似于 $@ 格式了,若要当成一个整体字符串出来,就把 for arg in ${args_str} 改成 for arg in "$*"
参考推荐:
Linux Make(Makefile)由浅入深的学习与示例剖析
Linux shell 脚本通过expect实现自动输入密码
nohup、&、disown、setsid、screen、jobs 后台运行命令区别
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2020-05-11 11:10:06
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!