【问题标题】:How to redirect output to a specific file into a sed command?如何将输出重定向到特定文件到 sed 命令?
【发布时间】:2016-12-28 00:28:22
【问题描述】:

一些上下文:我正在尝试构建一个通用的 Makefile,具有自动依赖生成功能(使用 GCC,如 here 所述,非递归,可以在我的项目的任何级别使用。 为此,生成的依赖文件需要采用以下形式:

$(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)\2|g' $(word 2,$^).tmp > $(word 2,$^)

%.o: %.c %.dep
    $(COMPILE)
    $(POSTCOMPILE)
    $(RM) $(word 2,$^).tmp
    touch $@

sed 调用将文件名之前的任何目录部分替换为$(DIR)

问题是由于依赖文件是在object文件之后生成的,所以导致Makefile每次都重新链接。所以我必须添加一个触摸命令以确保目标文件将被认为是最新的。这不是很优雅。 所以我有这个问题:有没有办法直接将 gcc 输出(定向到 .tmp 文件)重定向到 sed 命令中,而不是使用临时文件?

换句话说,有没有一种方法可以做管道重定向的等价物,但对于 stdout 以外的其他流/文件描述符?

【问题讨论】:

  • 在 GNU sed 中有 s/pattern/replacement/w file ,它将向命名文件写入替换。你可以使用s/.*/&amp;/w yourFile
  • 您的问题的答案是否定的,没有办法做到这一点。无论如何,您无论如何都需要touch,因为无法 100% 确定 sed 命令会在编译器完成写入目标文件之前完成其文件的写入:它们是并行运行的,所以您不能保证哪个先完成。

标签: shell gcc sed makefile io-redirection


【解决方案1】:

如果您处于成熟的 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)\2|g' > $(word 2,$^)
DEPFLAGS = -MT $@ -MP -MMD -MF >($(SED_COMMAND))
COMPILE = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

%.o: %.c %.dep
        $(COMPILE)
        touch $@

但是,这仍然需要在最后使用touch 命令,原因在上面@MadScientist 的评论中正确提到:

没有办法 100% 确定 sed 命令会在编译器完成写入目标文件之前完成其文件的写入:它们是并行运行的,因此您无法保证哪个会先完成。

【讨论】:

  • 谢谢,这正是我正在搜索的内容(尽管我仍然需要触摸文件)。这是特定于 Linux 还是 Bash ? (我在 Linux 和 MacO 上工作,因为我的学校使用 Mac)。
  • 进程替换是一种特定于 bash 的结构,仅在某些环境中可用:桌面 Linux 和 MacOS 就在其中。
猜你喜欢
  • 2018-06-07
  • 2015-10-30
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 2015-10-13
  • 2022-01-24
  • 2016-09-09
  • 2021-09-09
相关资源
最近更新 更多