shell脚本中的特殊变量
1. $# 传递到脚本的参数个数
2. $* 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
3. $$ 脚本运行的当前进程ID号
4. $! 后台运行的最后一个进程的进程ID号
5. $@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
6. $- 显示shell使用的当前选项,与set命令功能相同
7. $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$0 | 脚本名字 |
$1 | 位置参数 #1 |
$2 - $9 | 位置参数 #2 - #9 |
${10} | 位置参数 #10 |
$# | 位置参数的个数 |
"$*" | 所有的位置参数(作为单个字符串) * |
"$@" | 所有的位置参数(每个都作为独立的字符串) |
${#*} | 传递到脚本中的命令行参数的个数 |
${#@} | 传递到脚本中的命令行参数的个数 |
$? | 返回值 |
$$ | 脚本的进程ID(PID) |
$- | 传递到脚本中的标志(使用set ) |
$_ | 之前命令的最后一个参数 |
$! | 运行在后台的最后一个作业的进程ID(PID) |
makefile中的自动化变量
下面对所有的自动化变量进行说明:
$@
表示规则的目标文件名。如果目标是一个文档文件( Linux 中,一般称 .a 文件为文档文件,也称为静态库文件),那么它代表这个文档的文件名。在多目标模式规则中,它代表的是哪个触发规则被执行的目标文件名。
$%
当规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则的目标是“ foo.a(bar.o) ”,那么,“ $% ”的值就为“ bar.o ”,“ $@ ”的值为“ foo.a ”。如果目标不是静态库文件,其值为空。
$<
规则的第一个依赖文件名。如果是一个目标文件使用隐含规则来重建,则它代表由隐含规则加入的第一个依赖文件。
$?
所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代表的是库成员( .o 文件)。
$^
规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有库成员( .o 文件)名。一个文件可重复的出现在目标的依赖中,变量“ $^ ”只记录它的一次引用情况。就是说变量“ $^ ”会去掉重复的依赖文件。
$+
类似“ $^ ”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。
$*
在模式规则和 静态模式规则 中,代表“茎”。“茎”是目标模式中“ % ”所代表的部分(当文件名中存在目录时,“茎”也包含目录(斜杠之前)部分)。例如:文件“ dir/a.foo.b ”,当目标的模式为“ a.%.b ”时,“ $* ”的值为“ dir/a.foo ”。“茎”对于构造相关文件名非常有用。
自动化变量“ $* ”需要两点说明:
? 对于一个明确指定的规则来说不存在“茎”,这种情况下“ $* ”的含义发生改变。此时,如果目标文件名带有一个可识别的后缀,那么“ $* ”表示文件中除后缀以外的部分。例如:“ foo.c ”则“ $* ”的值为:“ foo ”,因为 .c 是一个可识别的文件后缀名。 GUN make 对明确规则的这种奇怪的处理行为是为了和其它版本的 make 兼容。通常,在除静态规则和模式规则以外,明确指定目标文件的规则中应该避免使用这个变量。
? 当明确指定文件名的规则中目标文件名包含不可识别的后缀时,此变量为空。
自动化变量“ $? ”在显式规则中也是非常有用的,使用它规则可以指定只对更新以后的依赖文件进行操作。例如,静态库文件“ libN.a ”,它由一些 .o 文件组成。这个规则实现了只将更新后的 .o 文件加入到库中:
lib: foo.o bar.o lose.o win.o
ar r lib $?
以上罗列的自动量变量中。其中有四个在规则中代表文件名( $@ 、 $< 、 $% 、 $* )。而其它三个的在规则中代表一个文件名列表。 GUN make 中,还可以通过这七个自动化变量来获取一个完整文件名中的目录部分和具体文件名部分。在这些变量中加入“ D ”或者“ F ”字符就形成了一系列变种的自动环变量。这些变量会出现在以前版本的 make 中,在当前版本的 make 中,可以使用“ dir ”或者“ notdir ”函数来实现同样的功能。
$(@D)
表示目标文件的目录部分(不包括斜杠)。如果“ $@ ”是“ dir/foo.o ”,那么“ $(@D) ”的值为“ dir ”。如果“ $@ ”不存在斜杠,其值就是“ . ”(当前目录)。注意它和 函数“ dir” 的区别!
$(@F)
目标文件的完整文件名中除目录以外的部分(实际文件名)。如果“ $@ ”为“ dir/foo.o ”,那么“ $(@F) ”只就是“ foo.o ”。“ $(@F) ”等价于函数“ $(notdir $@) ”。
$(*D)
$(*F)
分别代表目标“茎”中的目录部分和文件名部分。
$(%D)
$(%F)
当以如“ archive(member) ”形式静态库为目标时,分别表示库文件成员“ member ”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效。
$(<D)
$(<F)
分别表示规则中第一个依赖文件的目录部分和文件名部分。
$(^D)
$(^F)
分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)。
$(+D)
$(+F)
分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)。
$(?D)
$(?F)
分别表示被更新的依赖文件的目录部分和文件名部分。
在讨论自动化变量时,为了和普通变量(如:“ CFLAGS ”)区别,我们直接使用了“ $< ”的形式。这种形式仅仅是为了和普通变量进行区别,没有别的目的。其实对于自动环变量和普通变量一样,代表规则第一个依赖文件名的变量名实际上是“ < ”,我们完全可以使用“ $(<) ”来替代“ $< ”。但是在引用自动化变量时通常的做法是“ $< ”,因为自动化变量本身是一个特殊字符。
GUN make 同时支持“ Sysv ”特性,允许在规则的依赖列表中使用特殊的变量引用(一般的自动化变量只能在规则的命令行中被引用)“ $$@ ”、“ $$(@D) ”和“ $$(@F) ”(注意:要使用“ $$ ”),它们分别代表了“目标的完整文件名”、“目标文件名中的目录部分”和“目标的实际文件名部分”。这三个特殊的变量只能用在明确指定目标文件名的规则中或者是静态模式规则中,不用于隐含规则中。另外 Sysv make 和 GNU make 对规则依赖的处理也不尽相同。 Sysv make 对规则的依赖进行两次替换展开,而 GUN make 对依赖列表的处理只有一次,对其中的变量和函数引用直接进行展开。
自动化变量的这个古怪的特性完全是为了兼容 Sysv 版本的 makefile 文件。在使用 GNU make 时可以不考虑这个,也可以在 Makefile 中使用伪目标“ .POSIX ”来禁止这一特性。