user1654361
user1654361

Reputation: 369

Makefile: How to apply an equivalent to filter on multiple wildcards

I am writing a Makefile and I get stuck on a filter function limitation. Indeed, filter takes only one wildcard.

What I would like to do is: I have a list a files, some matching the regexp blabla, some not. But for this I need 2 wildcards, thus i cannot use filter function.

I would like to split my original list in 2 lists, one containing all the element containing the blabla string (filter equivalent) and the other one containing the not matching one (filter-out equivalent).

thanks for your help.

Upvotes: 6

Views: 8539

Answers (3)

Idelic
Idelic

Reputation: 15582

You can do this without running any external commands. Define the two macros

containing = $(foreach v,$2,$(if $(findstring $1,$v),$v))
not-containing = $(foreach v,$2,$(if $(findstring $1,$v),,$v))

Now you can do

LIST := a_old_tt x_old_da a_new_da q_ty_we
LIST_OLD := $(call containing,old,$(LIST))
LIST_NOT_OLD := $(call not-containing,old,$(LIST))

Upvotes: 11

Reinier Torenbeek
Reinier Torenbeek

Reputation: 17383

You could take advantage of your shell's more advanced string handling capabilities. Assuming that you have bash, you could use the following in your makefile:

LIST := a_old_tt x_old_da a_new_da q_ty_we
LIST_NOT_OLD := $(shell l=($(LIST)); echo $${l[@]//*old*})
LIST_OLD := $(filter-out $(LIST_NOT_OLD),$(LIST))

You can find an explanation of the bash string replacement mechanism in how to delete elements from an array based on a pattern. The double $ is required to keep the $ sign in the shell invocation.

Upvotes: 1

Beta
Beta

Reputation: 99134

One of Make's greatest shortcomings is its poor ability to handle regular expressions. The functions filter and filter-out can't find "old" in the middle of a word. I'd suggest this hack:

NOT_OLD = $(shell echo $(LIST) | sed 's/[^ ]*old[^ ]* *//g')
OLD = $(filter-out $(NOT_OLD), $(LIST))

Upvotes: 3

Related Questions