Reputation: 369
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
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
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
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