24

是否有可能删除单词列表中的重复项而不在 makefile 中排序?

$(sort foo bar lose)

确实删除了重复项(这对我来说是这种情况下的主要功能),但也有排序(对我来说,在这种情况下是一个不幸的副作用)。我想避免这种情况。

[更新]

bobbogo的回答效果很好。只记得使用define uniqv3.81 和(没有检查这个)define uniq =以后的版本。

如果您的记录分隔符不是空格,则larsmans的回答也非常有效,例如,如果您想从中删除重复项_foo_bar_lose_lose_bar_baz_等。只要记住使用RSand ORSawk 选项而不是tr, 并用$(firstword $(shell ... ))

4

4 回答 4

34

基于无聊$eval的方法:

define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

w := z z x x y c x

$(info $(sort $w))
$(info $(call uniq,$w))

极其可怕的使标准库递归调用(递归使被认为是极其可怕的?):

uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))

值得注意的是,在第二个公式中没有损坏任何变量(见seen第一个)。最好只是这样做(鉴于make中缺乏当地人)!

编辑

我对上述递归 make 的晦涩评论似乎使情况有些混乱。在这篇文章的上下文中,“递归”是指递归函数它实际上与可恶的递归 make无关。

uniq的后一个(递归)定义非常好,性能好,体积小,绝对是可以使用的。

于 2013-04-22T15:41:49.050 回答
13

取决于你在哪里需要它以及你是否使用 GNU make。如果您只想对目标先决条件列表进行 uniq,那么它就像 ( http://www.gnu.org/software/make/manual/make.html#Quick-Reference ) 一样简单:

$^ 的值省略了重复的先决条件,而 $+ 保留它们并保留它们的顺序。

所以,像这样的规则

exe: $(OBJS)
        $(LD) -o $@ $^

将自动过滤 $(OBJS) 中的重复项,同时仍保持其他项目的顺序相同。

于 2015-10-23T23:39:44.463 回答
7

You could echo the words through awk:

echo foo bar foo baz bar | tr ' ' '\n' | awk '!a[$0]++'

Deduping one-liner taken from catonmat.

(Don't forget to double the $ to $$ in a Makefile.)

于 2013-04-22T10:07:24.120 回答
0

以下适用于我在 GNU make v3.82 下:

uniq = $(eval _uniq := $1)$(strip $(foreach _,$(_uniq),$(if $(filter $_,$(_uniq)),$(eval _uniq := $(filter-out $_,$(_uniq)))$_)))

它不会通过在 中创建副本来修改其输入_uniq,并且它不是递归的。

于 2019-10-11T11:45:33.553 回答