bash 为什么 AWK 在 makefile 中不能正常工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30445218/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:02:27  来源:igfitidea点击:

Why does AWK not work correctly in a makefile?

bashawkmakefilesh

提问by Anton Riab

NOTICE: Escaping not problem, sample from shell is only sample, in Makefile $$.

注意:转义没问题,来自shell的样本只是样本,在Makefile $$中。

GNU Makefile mansays why it's doesn't work:

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

Note that expansion using ‘%' in pattern rules occurs after any variable or function expansions, which take place when the makefile is read.

请注意,在模式规则中使用 '%' 的扩展发生在任何变量或函数扩展之后,这发生在读取 makefile 时。

--Orig. question:
In pure shell, the next script works correctly:

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

echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
awk 'BEGIN{RS=" "}{if(NR == 1) f=
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=$
...%.cpp $(SOURCES)  | awk '{print ("file1.cpp" ~ $)"."$"."length($)}' )
; else if($
...%.cpp $(SOURCES) | awk 'BEGIN{RS=" "}{if(NR == 1) f=$
...%.cpp $(SOURCES) : $(shell echo %.cpp $(SOURCES) | awk '{print "src/"$}' )
".cpp"; print ("file1.cpp.cpp" ~ f)"."("file1.cpp" ~ f)"."f"."length(f)}' )
~ f) print $
...%.cppppppp $(SOURCES) | awk '{print ("file1.cpp" ~ $)"."$"."length($)}' )
;}' ) @mkdir -p $(OBJ_DIR) @$(CC) -c $< -o $@ $(addprefix -I,$(LOCAL_PATHS_HEADERS))
; else if(match(
echo "test2.cpp src2/test2.cpp src1/test1.cpp src1/test.cpp" | \
awk 'BEGIN{RS=" "}{if(NR == 1) f=$##代码##; else if(match($##代码##, f)) print $##代码##;}'
, f)) print ##代码##;}'

Filter is first: test1.cpp
And it returns: src1/test1.cpp

过滤器首先是: test1.cpp
并返回: src1/test1.cpp

But in Makefile it does not work correctly (error compared to awk):

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

##代码##

So I take simple in Makefileand check value f, and found some strange length of f

所以我在Makefile中取simple并检查值f,发现f的一些奇怪的长度

##代码##

awk return fail in compared; print returns "0.file1.cpp.5" to fail with length, because it has forgotten .cppvalue of %, info bellow. I attempted to correct it:

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

##代码##

but awk return fail in all compared; print returns "0.0.file1.cpp.cpp.9".

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

I check awk in manual mode, like this:

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

##代码##

It works fine, but it isn't variant, because it will kill automatic mode.

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

--Add
Information about lost length from parameter % to AWK

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

##代码##

print returns "0.test2.cppppppp.10"

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

--Upd, some problem
Above, I was printing return value from $<
But file redirect show that value % does not work in prerequisites(file redirect: "0.%.cpp.5").

--Upd,一些问题
上面,我正在打印返回值$<
但文件重定向显示值 % 在先决条件中不起作用(文件重定向:“0.%.cpp.5”)。

Can I use any automatic variable with value in prerequisites?

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

回答by William Pursell

Almost invariably, when a question is asked about awk in a Makefile, the solution is to properly escape the $symbols. It's not entirely clear what your question is, but there are some substantial misunderstandings that need to be resolved. In particular, the following "works", but hardly for the reasons you think:

几乎无一例外,当在 Makefile 中询问有关 awk 的问题时,解决方案是正确转义$符号。您的问题是什么并不完全清楚,但有一些实质性的误解需要解决。特别是,以下“有效”,但几乎不是您认为的原因:

##代码##

You almost certainly do not want $$in any of the cases they appear here. awkis generally looking for single dollar signs, and when they appear in a Makefile, they are doubled because Make parses the $$and invoked awkwith a single $. In the quoted sample, $$0on the first record is equivalent to $test2.cpp, but the variable test2.cppis uninitialized and so has value 0, so on the first pass f is set to the value of $0 (the string "test2.cpp").

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

In short, if you are invoking awk from the shell, use single $. In the Makefile, use $$and awk will only see $.

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