我最近在学习GNU make。以下是GNU make手册中自动依赖生成的示例。我知道上面脚本的一般含义(它基本上用sed
命令替换了其他东西)。但是我对命令中的细节有两个问题。首先,\1.o
在命令中意味着什么?它与位置参数有关吗?第二,为什么$*
被放入一对()
,因为$*
本身已经意味着目标文件名的干? (我试过没有括号,它没有用。)
%.d: %.c
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
我尝试了以下内容,但没有奏效。
%.d: %.c
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,$*\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
任何人都可以解释背后的原因吗?感谢。
答案 0 :(得分:4)
文字为interpreted multiple times。
's,\($*\)\.o[ :]*,\1.o $@ : ,g'
在第一步中,Make展开$
个变量。例如:
's,\(foo\)\.o[ :]*,\1.o foo.d : ,g'
接下来,将此字符串传递给Shell,它会剥离引号。
s,\(foo\)\.o[ :]*,\1.o foo.d : ,g
最后,它由sed
解释。在sed
默认情况下理解的基本正则表达式中,\(…\)
只匹配…
,但分组匹配。然后,在替换中,您可以返回匹配的文本。 \N
指的是匹配的 N 组。因此,在此示例中,\1
只会引用任何匹配的$*
- 可能foo
。 (如果$*
扩展为正则表达式中具有特殊含义的内容,则可能会遇到麻烦。请注意,后引用使正则表达式非常规,但这可能与此无关。)
根据我的理解,这不是一种非常强大的编写替换方法,并且实际上不需要在这里使用反向引用。通过像这样的替代品可以更加稳健地实现期望的效果。
's,[^:]*:,$*.o $@ :,g'