2013-04-22 12 views
13

Gibt es eine Möglichkeit, Duplikate in einer Liste von Wörtern zu entfernen, ohne in einem Makefile zu sortieren?Makefile: doppelte Wörter ohne Sortierung entfernen

$(sort foo bar lose) 

tun Duplikate entfernen (was für mich ist die Hauptfunktionalität in diesem Fall), sondern sortiert auch (für mich eine unglückliche Nebenwirkung in diesem Fall). Ich möchte das vermeiden.

[update]

bobbogo ‚s Antwort funktioniert sehr gut. Denken Sie daran, define uniq für v3.81 zu verwenden und (nicht überprüft) define uniq = für spätere Versionen.

larsmans 'Antwort funktioniert auch sehr schön wenn Ihre voneinander zu trennen sind kein Raum ist, z.B. wenn Du Duplikate von _foo_bar_lose_lose_bar_baz_ oder ähnlichem entfernen willst. Denken Sie daran, verwenden, um die RS und ORS awk Optionen statt tr und wickeln sie alle mit $(firstword $(shell ...))

+2

Es gibt keine make-in-Operation, die das tun kann. Sie müssen eine Shell-Operation verwenden. – MadScientist

Antwort

17

Boring $eval basierte Methode:

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

Extrem fiendish make Standardbibliothek rekursiven Aufruf ("rekursiven make extrem teuflisch betrachtet ?):

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

Es tut mir leid, das scheint nicht zu funktionieren. $ (info $ (sort $ w)) gibt das sortierte Array aus, aber $ (info $ (call uniq, $ w)) gibt nichts aus. Ich finde es jedoch eine sehr clevere Lösung. Vielleicht braucht es nur eine kleine Modifikation? – parvus

+0

@parvus Welche Version von make verwenden Sie? '$ (eval ...)' ist relativ neu, obwohl ich denke, dass die teuflische Lösung relativ portabel sein sollte. – bobbogo

+1

'define blah =' ist noch jünger. Vielleicht einfach das '=' wegnehmen? – bobbogo

6

Sie konnte die Worte durch awkecho:

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

deduping Einzeiler aus catonmat genommen.

(. Vergessen Sie nicht, die $ zu $$ in einem Makefile zu verdoppeln)

+1

Ok tx! Aber wie kann ich das Ergebnis in einer Zeichenfolge zurück erhalten? Awk gibt die Ergebnisse mit Zeilenumbrüchen, und ich muss das Ergebnis in einer Variablen gespeichert haben, damit ich es weitergeben kann. – parvus

+1

@parvus: ein extra '| tr '\ n' '' 'am Ende sollte das tun. (Nicht sehr elegant, gebe ich zu.) –

+0

Leider tut es das nicht. Es gibt dann "baz" ohne die Anführungszeichen aus. Wahrscheinlich, da ich dies in einer dummen DOS-Shell (mit einigen portierten GnuWin32-Dienstprogrammen wie awk und tr und so) versuche. Ich habe es nicht auf einem Linux-System ausprobiert, da diese Operation in einer reinen Windows-Umgebung benötigt wird. – parvus

5

Je nachdem, wo Sie es brauchen und ob Sie GNU make verwenden. Wenn Sie nur die Liste der Ziel Voraussetzungen Unik wollen, dann ist es so einfach wie (http://www.gnu.org/software/make/manual/make.html#Quick-Reference):

Der Wert von $^doppelte Voraussetzungen auslässt, während $ + sie behält und bewahrt ihre Reihenfolge.

So eine Regel wie

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

filtert Duplikate von $ (OBJS) automagically, noch während Auftrag anderer Elemente die gleiche bleibt.

Verwandte Themen