如何将输出重定向到特定文件到 sed 命令中?
How to redirect output to a specific file into a sed command?
一些上下文:我正在尝试构建一个通用的 Makefile,它具有自动依赖性生成(使用 here 所述的 GCC,非递归的,可以在我的项目的任何级别使用。
为此,生成的依赖文件需要采用以下形式:
$(DIR)file.o: $(DIR)file.c $(DIR)file.h
$(DIR)file.h
这样,无论 make 调用的级别如何,make 都可以正确定位文件。
为此,我有以下隐含规则:
DEPFLAGS = -MT $@ -MP -MMD -MF $(word 2,$^).tmp
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
POSTCOMPILE = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)|g' $(word 2,$^).tmp > $(word 2,$^)
%.o: %.c %.dep
$(COMPILE)
$(POSTCOMPILE)
$(RM) $(word 2,$^).tmp
touch $@
sed 调用将文件名之前的任何目录部分替换为 $(DIR)
问题是由于依赖文件是在object文件之后生成的,导致Makefile每次都relink。所以我必须添加一个触摸命令以确保目标文件将被视为最新的。这不是很优雅。
所以我有这个问题:有没有办法直接将 gcc 输出(定向到 .tmp 文件)重定向到 sed 命令,而不是使用临时文件?
换句话说,有没有办法做管道重定向的等价物,但对于另一个 stream/file 描述符而不是 stdout ?
如果您处于成熟的 linux 环境中,您确实可以跳过 .tmp 文件的创建并将依赖项直接通过管道传输到 sed
.
# This is needed, because the default shell does not support
# process substitution
SHELL = /bin/bash
SED_COMMAND = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)|g' > $(word 2,$^)
DEPFLAGS = -MT $@ -MP -MMD -MF >($(SED_COMMAND))
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
%.o: %.c %.dep
$(COMPILE)
touch $@
然而,这仍然需要最后的 touch
命令,原因在上面@MadScientist 的评论中正确提到:
there's no way to be 100% sure that the sed command would finish writing its file before the compiler finished writing the object file: they are running in parallel so you can't guarantee which one will finish first.
一些上下文:我正在尝试构建一个通用的 Makefile,它具有自动依赖性生成(使用 here 所述的 GCC,非递归的,可以在我的项目的任何级别使用。 为此,生成的依赖文件需要采用以下形式:
$(DIR)file.o: $(DIR)file.c $(DIR)file.h
$(DIR)file.h
这样,无论 make 调用的级别如何,make 都可以正确定位文件。
为此,我有以下隐含规则:
DEPFLAGS = -MT $@ -MP -MMD -MF $(word 2,$^).tmp
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
POSTCOMPILE = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)|g' $(word 2,$^).tmp > $(word 2,$^)
%.o: %.c %.dep
$(COMPILE)
$(POSTCOMPILE)
$(RM) $(word 2,$^).tmp
touch $@
sed 调用将文件名之前的任何目录部分替换为 $(DIR)
问题是由于依赖文件是在object文件之后生成的,导致Makefile每次都relink。所以我必须添加一个触摸命令以确保目标文件将被视为最新的。这不是很优雅。 所以我有这个问题:有没有办法直接将 gcc 输出(定向到 .tmp 文件)重定向到 sed 命令,而不是使用临时文件?
换句话说,有没有办法做管道重定向的等价物,但对于另一个 stream/file 描述符而不是 stdout ?
如果您处于成熟的 linux 环境中,您确实可以跳过 .tmp 文件的创建并将依赖项直接通过管道传输到 sed
.
# This is needed, because the default shell does not support
# process substitution
SHELL = /bin/bash
SED_COMMAND = sed -E 's|([0-9a-z_.:]*/)?([0-9a-z_.:]+)|$$(DIR)|g' > $(word 2,$^)
DEPFLAGS = -MT $@ -MP -MMD -MF >($(SED_COMMAND))
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
%.o: %.c %.dep
$(COMPILE)
touch $@
然而,这仍然需要最后的 touch
命令,原因在上面@MadScientist 的评论中正确提到:
there's no way to be 100% sure that the sed command would finish writing its file before the compiler finished writing the object file: they are running in parallel so you can't guarantee which one will finish first.