2012-09-07 5 views
5

Sto scrivendo un Makefile e mi blocco su una limitazione della funzione filtro. Infatti, il filtro accetta solo un carattere jolly.Makefile: Come applicare un equivalente al filtro su più caratteri jolly

Quello che vorrei fare è: Ho una lista di un file, alcuni corrispondenti all'espressione regolare blabla, altri no. Ma per questo ho bisogno di 2 caratteri jolly, quindi non posso usare la funzione filtro.

Vorrei dividere la mia lista originale in 2 liste, una contenente tutto l'elemento che contiene la stringa blabla (equivalente del filtro) e l'altra che contiene quella non corrispondente (equivalente al filtro).

grazie per il vostro aiuto.

+1

Si sta utilizzando GNU make o qualche altra variante? E mostra il tuo codice attuale, non è chiaro quale sia il problema. – Gilles

+1

Fornire un elenco di esempio di file, espressione del filtro e risultato desiderato. Il modo in cui lo descrivi ora, non mi è chiaro perché le funzioni '$ (filter ...)' e '$ (filter-out ...)' non sono abbastanza buone per te. –

+0

Grazie per la risposta. Sto usando gnu make. Non ho il codice da mostrare perché non riesco a capire come scriverlo. Dire che ho ELENCO = a_old_tt x_old_da a_new_da q_ty_we. Desidero ordinare il contenuto LIST in: LIST_OLD che contiene tutti i membri di LIST contenenti l'espressione old (a_old_tt e x_old_da nel mio esempio) e LIST_NOT_OLD che contiene tutti i membri di LIST che non contengono l'espressione precedente (a_new_da q_ty_we in il mio esempio). – user1654361

risposta

1

Uno dei maggiori difetti di Make è la scarsa capacità di gestire le espressioni regolari. Le funzioni filter e filter-out non riescono a trovare "vecchio" nel mezzo di una parola. Suggerisco questo trucco:

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

È possibile sfruttare le funzionalità di gestione delle stringhe più avanzate della shell. Supponendo che avete bash, è possibile utilizzare il seguente nella vostra 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)) 

Si può trovare una spiegazione del meccanismo di bash sostituzione di stringa in how to delete elements from an array based on a pattern. Il doppio $ è necessario per mantenere il segno $ nella chiamata della shell.

7

È possibile eseguire questa operazione senza eseguire alcun comando esterno. Definire le due macro

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

ora si può fare

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)) 
+0

+1, sembra ragionevole, personalmente lo implementerei allo stesso modo. –

+0

Limitare se hai bisogno di espressioni regolari complete per calcolare il 'contenitore' booleano, ma funziona per questo caso particolare. Personalmente non mi preoccuperei dei comandi esterni, dal momento che la performance/inner loop di Make sarà molto probabilmente nella destinazione, nel comando build/compile. –

+0

Certo, come Beta ha detto nella sua risposta, 'make' non può occuparsi di espressioni regolari, quindi se ne hai bisogno (ma OP no), ovviamente non puoi usare questa risposta. La prima reazione a questo problema è spesso quella di far uscire i grandi cannoni e invocare un comando esterno per eseguire l'abbinamento, ma come dimostra questo caso, può essere un enorme esagerazione. Evito di eseguire i comandi esterni il più possibile, sia per la portabilità che per la velocità. Ho visto enormi miglioramenti nelle prestazioni eliminando inutili comandi esterni in grandi sistemi di build basati su make. – Idelic