makefile
seq.d : seq.c @set -e; \ gcc -MM $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ -include seq.d
第一个命令
@set -e
。@关键字告诉make不输出该行命令;set -e的作用是,当后面的命令的返回值非0时,立即退出。那么为什么要把几个命令写在”同一行“(是对于make来说,因为\的作用就是连接行),并用分号隔开每个命令?因为在Makefile这样做才能使上一个命令作用于下一个命令。这里是想要set -e作用于后面的命令。
第二个命令
gcc -MM $< > $@.$$$$
, 作用是根据源文件生成依赖关系,并保存到临时文件中。内建变量$<
的值为第一个依赖文件(那seq.c),$$$$
为字符串"$$"
,由于makefile中所有的$字符都是特殊字符(即使在单引号之中!),要得到普通字符$,需要用$$
来转义; 而$$
是shell的特殊变量,它的值为当前进程号;使用进程号为后缀的名称创建临时文件,是shell编程常用做法,这样可保证文件唯一性。第三个命令作用是将目标文件加入依赖关系的目录列表中,并保存到目标文件。关于正则表达式部分就不说了,唯一要注意的是内建变量
$*
,$*
的值为第一个依赖文件去掉后缀的名称(这里即是seq)。第四个命令是将该临时文件删除。
我的理解:------------------其中 英文的单引号:
1、由单引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后,也会失去原有意义,而只作为普通字符解释。如例程中的 '-1 day',再比如:$ string=’$PATH’ $ echo $string $PATH $ 可见$保持了其本身的含义,作为普通字符出现。
2、由双引号括起来的字符,除$(美元符号)、\(反斜杠)、’(单引号)、和”(双引号)这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。对于“$”来说,就是用其后指定的变量的值来代替这个变量和$;对于“\”而言,是转义字符,它告诉shell不要对其后面的那个字符进行特殊处理,只当作普通字符即可。可以想见,在双引号中需要在前面加上“\”的只有四个字符$,\,’和”本身。而对”号,若其前面没有加“\”,则Shell会将它同前一个”号匹配。如例程中的"-$i day",会随着循环,将$i转换成其代表的值。
3、反引号(`)这个字符所对应的键一般位于键盘的左上角,不要将其同单引号(’)混淆。反引号括起来的字符串被shell解释为命令行,在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分。如例程中的`date -d '-1 day' +%Y%m%d`就是把这条命令的结果赋给变量OPDATE。
4、反引号还可以嵌套使用。但需注意,嵌套使用时内层的反引号必须用反斜杠(\)将其转义。例如: $ abc=`echo The number of users is \`who| wc -l\`` $ echo $abc The number of users is 2 $ 5、在反引号之间的命令行中也可以使用shell的特殊字符。Shell为得到``中命令的结果,它实际上要去执行``中指定的命令。执行时,命令中的特殊字符,如$,”,?等又将具有特殊含义,并且``所包含的可以是任何一个合法的Shell命令,如: $ ls note readme.txt Notice Unix.dir $ TestString="`echo $HOME ` ` ls [nN]*`" $ echo $TestString /home/yxz note Notice
最后,说句题外话: 反引号是一个老的用法,$()才是新的用法,如例程中的$(seq 10)。无论是在学习中,还是在实际工作中,$()都是被推荐的用法。所以上面的的用法可以改成:
$ TestString="$(echo $HOME) $(ls [nN]*)"
$ echo $TestString
/home/yxz note Notice
对于脚本的执行情况,可以用下面的命令来分析:
sh -x test.sh
------------------逗号,的作用是作为分隔符,作用等同于s///g中的斜杠
-------------------\($*\)\.o
\($*\)表示匹配$*,后面使用\1表示它;\(\)出现一次用\1匹配,如果出现多次,分别用\2、\3...匹配
$*表示去掉文件的后缀,只留下基础名字
\.表示点"."
----------------- < $@.$$$$
将($@.$$$$)的临时文件中的字符串信息(main.o:main.c defs.h)通过 “<” 输送到sed命令中.
$$$$:
书里面说 .$$$$是当前进程好。 然到Makefile这个脚本将$$$$当成进程号了。姑且这么认为吧。
-------------------- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$
这个产生的,我个人认为:
比如cc -MM main.cc
这句产生的就是 main.o : main.d
在$@之后又空格和冒号嘛,我就这样理解的。
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
最新推荐文章于 2024-07-25 14:13:11 发布