【问题标题】:Why does AWK not work correctly in a makefile? [duplicate]为什么 AWK 在 makefile 中不能正常工作? [复制]
【发布时间】:2015-08-07 08:10:20
【问题描述】:

注意:转义不是问题,shell 中的示例只是示例,在 Makefile $$ 中。

GNU Makefile man 说明为什么它不起作用:

请注意,在模式规则中使用 '%' 的扩展发生在任何 变量或函数扩展,在生成文件时发生 阅读。

--原件。问题:
在纯 shell 中,下一个脚本可以正常工作:

echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
awk 'BEGIN{RS=" "}{if(NR == 1) f=$0; else if(match($0, f)) print $0;}'

过滤器是第一个:test1.cpp
它返回:src1/test1.cpp

但在 Makefile 中它不能正常工作(与 awk 相比有错误):

OBJ_DIR:=obj    
SOURCES:=$(wildcard */*.cpp *.cpp)
OBJECTS_LOCAL:= $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.cpp=.o)))
LOCAL_PATHS_HEADERS:=$(sort $(dir $(wildcard *.h */*.h)))

TARGET:=libcommon.a

all:$(TARGET)

$(TARGET): $(OBJECTS_LOCAL)
        ar -rcs $@ $^

$(OBJECTS_LOCAL): $(OBJ_DIR)/%.o : $(shell echo %.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0; else if($$0 ~ f) print $$0;}' )
        @mkdir -p $(OBJ_DIR)
        @$(CC) -c $< -o $@ $(addprefix -I,$(LOCAL_PATHS_HEADERS))

于是我用简单的在Makefile中检查了f的值,发现f的长度有些奇怪

...%.cpp $(SOURCES)  | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )

awk 在比较中返回失败; print 返回“0.file1.cpp.5”以失败,因为它忘记了 .cpp% 的值,信息如下。我试图纠正它:

...%.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0".cpp"; print ("file1.cpp.cpp" ~ f)"."("file1.cpp" ~ f)"."f"."length(f)}' )

但是 awk 的返回结果在所有比较中都失败了;打印返回“0.0.file1.cpp.cpp.9”。

我在手动模式下检查 awk,如下所示:

...%.cpp $(SOURCES) : $(shell echo %.cpp $(SOURCES) | awk '{print "src/"$$1}' )

它工作正常,但它不是变体,因为它会杀死自动模式。

--添加
从参数 % 到 AWK 的丢失长度信息

...%.cppppppp $(SOURCES) | awk '{print ("file1.cpp" ~ $$1)"."$$1"."length($$1)}' )

打印返回“0.test2.cppppppp.10”

--更新,有点问题
上面,我正在打印来自 $&lt; 的返回值
但是文件重定向显示值 % 在先决条件中不起作用(文件重定向:“0.%.cpp.5”)。

我可以使用任何具有先决条件值的自动变量吗?

【问题讨论】:

    标签: bash awk makefile sh


    【解决方案1】:

    几乎总是,当在 Makefile 中询问有关 awk 的问题时,解决方案是正确转义 $ 符号。目前尚不完全清楚您的问题是什么,但有一些重大误解需要解决。特别是,以下“有效”,但几乎没有您认为的原因:

    echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
    awk 'BEGIN{RS=" "}{if(NR == 1) f=$$0; else if(match($$0, f)) print $$0;}'
    

    您几乎肯定不希望 $$ 在它们出现在这里的任何情况下。 awk 通常寻找单个美元符号,当它们出现在 Makefile 中时,它们会加倍,因为 Make 解析 $$ 并使用单个 $ 调用 awk。在引用的示例中,第一条记录上的$$0 等价于$test2.cpp,但变量test2.cpp 未初始化,因此值为0,因此在第一遍f 设置为$0 的值(字符串“ test2.cpp")。

    简而言之,如果您从 shell 调用 awk,请使用单个 $。在 Makefile 中,使用$$,awk 只会看到$

    【讨论】:

    • 谢谢。我在我的问题中更正了这个问题,但是 awk 在使用 $$ 的 Makefile 中无法正常工作
    • 乍一看,Makefile 中的 awk 看起来还不错,但是您如何确定 awk 的输出呢?由于 awk 的输出是由 make 在规则的依赖端解析的,所以你只是打印 $&lt; 吗? (您可以尝试将 awk 的输出重定向到文件)更重要的是,您为什么要尝试动态生成此列表?明确列出此类依赖项通常被认为是最佳实践。
    • 我只是打印$
    猜你喜欢
    • 2019-08-29
    • 2014-11-20
    • 2021-09-25
    • 2019-01-22
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2020-02-26
    • 2012-06-12
    相关资源
    最近更新 更多