Shell中除了前面的用户自定义变量和位置变量,还有一类预定义的特殊变量:
$# 命令行参数的个数 $* 所有命令行参数,有空格连成一个字符串 $@ 所有命令行参数,不同的元素 $? 上一条命令执行的返回值 $$ 当前进程的进程号 $! 上一个后台命令的进程号 $- 由当前shell设置的执行标志名组成的字符串
1. $#
$#的值是当前脚本的命令行参数的个数,如:
[peter@ibi-genome shell]$ cat param_num.sh #!/bin/bash echo $# [peter@ibi-genome shell]$ sh param_num.sh 0 [peter@ibi-genome shell]$ sh param_num.sh a b 2 [peter@ibi-genome shell]$ sh param_num.sh 1 2 3 3
2. $*和$@
$*和$@的值是当前脚本的所有的命令行参数,他们的区别类似于我们前面学过的数组中的${array[*]}和${array[@]},$*是一个由空格分隔的字符串,而$@则是分别等于每一个命令行参数的几个不同的值。$*和$@直接用echo输出时结果是一样的,但在双引号中时,如果循环输出,则可以看出他们的区别。如:
[peter@ibi-genome shell]$ cat all_param.sh #!/bin/bash echo $* echo $@ for i in "$*" do echo $i done for i in "$@" do echo $i done [peter@ibi-genome shell]$ sh all_param.sh 1 2 1 2 1 2 1 2 1 2
3. $?
Shell中,每一个命令执行完都会返回一个非负整数值,如果是0说明该命令执行成功,如果是一个大于0的值,则说明命令执行出了问题,具体是什么问题要看命令中是怎样定义的。
[peter@ibi-genome test]$ ls #ls查看当前目录下有一个tmp文件 tmp [peter@ibi-genome test]$ rm tmp #rm删除该文件成功(没有错误提示) [peter@ibi-genome test]$ echo $? #$?的值为0 0 [peter@ibi-genome test]$ mkdir tmp #新建tmp目录 [peter@ibi-genome test]$ rm tmp #rm删除tmp目录出错(不带选项的rm命令不能删除目录) rm: 无法删除"tmp": 是一个目录 [peter@ibi-genome test]$ echo $? #$?的值为1 1
使用$?可以轻松判断上一个命令的执行结果。
4. $$
$$的值是当前进程的进程号,如:
[peter@ibi-genome shell]$ cat test.sh #!/bin/bash echo $$ [peter@ibi-genome shell]$ sh test.sh & #直接放到后台运行,显示其进程号为28950 [1] 28950 [peter@ibi-genome shell]$ 28950 #程序中$$的值就是该进程的进程号28950
5. $!
$!的值是上一个后台命令的进程号,如:
[peter@ibi-genome test]$ sleep 10 & [1] 28851 [peter@ibi-genome test]$ echo $! 28851
6. $-
$-的值是当前Shell设置的所有的执行标志名,如:
[peter@ibi-genome shell]$ echo $- himBH [peter@ibi-genome shell]$ set -x ++ printf '\033]0;%s@%s:%s\007' peter ibi-genome '~/shell' [peter@ibi-genome shell]$ echo $- + echo himxBH himxBH ++ printf '\033]0;%s@%s:%s\007' peter ibi-genome '~/shell' [peter@ibi-genome shell]$ set +x + set +x [peter@ibi-genome shell]$ echo $- himBH
set -x是给当前Shell添加执行标志x,使其执行指令后,先显示该指令及其参数,用于跟踪输出。Shell执行标志我们在Shell脚本调试一节中还要学习。