2013-04-22 16 views
13

Esiste la possibilità di rimuovere i duplicati in un elenco di parole senza ordinare in un make-up?makefile: rimuovere le parole duplicate senza ordinamento

$(sort foo bar lose) 

fa rimuovere i duplicati (che è per me la funzionalità principale in questo caso), ma smista anche (per me un effetto collaterale in questo caso). Voglio evitarlo.

[update]

bobbogo risposta s' funziona molto bene. Basta ricordare di usare define uniq per la v3.81 e (non controllare questo) define uniq = per le versioni successive.

larsmans 'risposta funziona molto bene anche se vostro separatore di record non è uno spazio, ad esempio, se si desidera rimuovere i duplicati da _foo_bar_lose_lose_bar_baz_ o simili. Basta ricordarsi di utilizzare le opzioni RS e ORS awk al posto di tr, e avvolgere il tutto con $(firstword $(shell ...))

+2

Non esiste alcuna operazione integrata che possa farlo. Dovrai usare un'operazione di shell. – MadScientist

risposta

17

Boring $eval metodo basato:

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

Estremamente diabolico trucco di serie chiamata ricorsiva biblioteca ("make ricorsivo considerato estremamente diabolico ? "):

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

Mi dispiace, questo non sembra funzionare. $ (info $ (ordina $ w)) stampa l'array ordinato, ma $ (info $ (chiama uniq, $ w)) non stampa nulla. Trovo comunque una soluzione molto intelligente. Forse richiede solo una piccola modifica? – parvus

+0

@parvus Quale versione di marca stai usando? '$ (eval ...)' è relativamente recente, anche se penso che la soluzione diabolica dovrebbe essere relativamente portabile. – bobbogo

+1

'define blah =' è ancora più recente. Forse basta togliere il '='? – bobbogo

6

Si potrebbe echo le parole attraverso awk:

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

deduping one-liner preso da catonmat.

(. Non dimenticate di raddoppiare la $ a $$ in un Makefile)

+1

Ok tx! Ma come posso ottenere il risultato in una stringa? Awk fornisce i risultati con le nuove righe e ho bisogno di avere il risultato memorizzato in una variabile in modo che io possa passarlo in giro. – parvus

+1

@parvus: un extra '| tr '\ n' '' 'alla fine dovrebbe farlo. (Non molto elegante, lo ammetto). –

+0

Sfortunatamente no. Emette quindi "baz" senza le virgolette. Probabilmente da quando ho provato questo in una stupida shell DOS (con alcune utility GnuWin32 porting come awk e tr e così via). Non l'ho provato su un sistema Linux, poiché questa operazione è necessaria in un ambiente solo per Windows. – parvus

5

dipende da dove avete bisogno e se si utilizza GNU make. Se si desidera solo per uniq l'elenco dei prerequisiti di destinazione, è facile come (http://www.gnu.org/software/make/manual/make.html#Quick-Reference):

Il valore di $^omette prerequisiti duplicati, mentre $ + li mantiene e conserva il loro ordine.

Quindi, una regola come

exe: $(OBJS) 
     $(LD) -o [email protected] $^ 

filtrerà i duplicati da $ (OBJS) automagically, mentre ancora ordine di altri elementi della stessa lasciando.

Problemi correlati