2010-03-24 14 views
51

Mam dwa pliki A - nodes_to_delete i B - nodes_to_keep. Każdy plik ma wiele wierszy z numerycznymi identyfikatorami.bash, Linux: Ustaw różnicę między dwoma plikami tekstowymi

Chcę mieć listę numerycznych identyfikatorów, które są w nodes_to_delete, ale NIE w nodes_to_keep, np. alt text http://mathworld.wolfram.com/images/equations/SetDifference/Inline1.gif.

Robiąc to w bazie danych PostgreSQL jest nierozsądnie wolny. Czy można to zrobić za pomocą narzędzi Linux CLI?

AKTUALIZACJA: Wydaje się, że to praca Pythonica, ale pliki są naprawdę, naprawdę duże. Rozwiązałem niektóre podobne problemy używając uniq, sort i niektórych technik teorii zbiorów. To było o dwa lub trzy rzędy wielkości szybsze od odpowiedników w bazie danych.

+0

Jestem ciekaw, co przyjdzie odpowiedzi. Bash to trochę więcej segphault, uważam, że administrator systemu. Jeśli powiedziałbyś "w pythonie" lub "w php" lub cokolwiek byś nie poradził lepiej :) – extraneon

+0

Widziałem tytuł i byłem gotowy na bip niespójności w interfejsie użytkownika oraz na bardziej holly niż na forum pomocy. To mnie rozczarowało, kiedy przeczytałem faktyczne pytanie. :( – aehiilrs

Odpowiedz

83

Komenda comm to robi.

+9

A jeśli pliki nie są jeszcze posortowane, najpierw "sortuj" – extraneon

+2

+1 Oświecone, wspaniałe narzędzie, którego czuję się głupio, nie wiem. Dzięki! –

+5

@Adam Matan: o wiele więcej oświecenia dostępne w 'ls/bin/usr/bin | xargs man' –

1

Może trzeba lepszego sposobu, aby to zrobić w PostgreSQL, mogę dość dużo zakład, że nie będzie znaleźć szybszy sposób to zrobić przy użyciu plików płaskich. Powinieneś być w stanie zrobić proste sprzężenie wewnętrzne i zakładając, że oba id cols są indeksowane, które powinny być bardzo szybkie.

+0

Masz techniczną poprawność, a" wyjaśnij "obsługuje twoje roszczenie, ale po prostu nie działa dla bardzo dużych (~ dziesiątki milionów) tabel. –

+1

Tak, byłoby to ograniczone przez twoją pamięć, w przeciwieństwie do czegoś w rodzaju posortowanego komunikatora, ale pomyślałbym, że jeśli masz dwie tablice z tylko polem int, które możesz bez problemu dostać do dziesiątek milionów. –

+0

To prawda w teorii, ale po prostu nie działa z jakiegoś powodu. –

26

Ktoś pokazał mi jak dokładnie to zrobić w sh kilka miesięcy temu, a potem nie mogłem znaleźć go na chwilę ... i patrząc Natknąłem się na swoje pytanie. Oto ona:

set_union() { 
    sort $1 $2 | uniq 
} 

set_difference() { 
    sort $1 $2 $2 | uniq -u 
} 

set_symmetric_difference() { 
    sort $1 $2 | uniq -u 
} 
+1

Myślę, że to jest lepsze niż zaakceptowana odpowiedź ... '' comm'' nie jest dostępny we wszystkich środowiskach. – danwyand

+0

I 'comm' również nie działa na' stdin' – wieczorek1990

+3

To jest różnica symetryczna, a nie normalna różnica zestawu. – Tgr

1

użycie comm - będzie porównać dwa posortowane pliki linia po linii

Odpowiedź na pytanie OP stosując ten przykład konfiguracja znajduje się poniżej. To polecenie zwróci linie unikatowe dla deleteNodes, a nie w keepNodes

comm -1 -3 <(sort keepNodes) <(sort deleteNodes) 

wyjaśnienie: pokaz unikatowej linii do deleteNodes, ukryć inne linie


przykład konfiguracja

Użyjemy keepNodes i deleteNodes. Są używane jako nieposortowane dane wejściowe.

$ cat > keepNodes <(echo bob; echo amber;) 
$ cat > deleteNodes <(echo bob; echo ann;) 

Domyślnie bez argumentów, drukuje Comm 3 kolumny

unique_to_FILE1 
    unique_to_FILE2 
     lines_appear_in_both 

To Barebone przykładem comm bez argumentów. Zwróć uwagę na trzy kolumny.

$ comm <(sort keepNodes) <(sort deleteNodes) 
amber 
    ann 
     bob 

Tłumienie wyjściu jednokolumnowym

zwalczaniu kolumna 1, 2 albo 3, -N; pamiętaj, że gdy kolumna jest ukryta, biała spacja maleje.

$ comm -1 <(sort keepNodes) <(sort deleteNodes) 
ann 
    bob 
$ comm -2 <(sort keepNodes) <(sort deleteNodes) 
amber 
    bob 
$ comm -3 <(sort keepNodes) <(sort deleteNodes) 
amber 
    ann 
$ comm -1 -3 <(sort keepNodes) <(sort deleteNodes) 
ann 
$ comm -2 -3 <(sort keepNodes) <(sort deleteNodes) 
amber 
$ comm -1 -2 <(sort keepNodes) <(sort deleteNodes) 
bob 

To nie wdzięcznie, gdy zapomni się uporządkować

comm: file 1 is not in sorted order

+0

+1 dla poprawnych przykładów, które zawierają odpowiedź na konkretne pytanie OP (linie wyjściowe w 'deleteNodes', które nie są w' keepNodes'), ale byłoby lepiej, gdyby poprawne rozwiązanie zostało podświetlone: ​​'comm -1 -3 <(sortuj keepNodes) <(sort delete deleteodes) '. –

1

comm został zaprojektowany specjalnie dla tego rodzaju przypadków użycia, ale wymaga wkładu posortowana.

awk jest prawdopodobnie lepszym narzędziem do tego, ponieważ jest dość proste do znalezienia różnicy w ustawieniach, nie wymaga sort i oferuje dodatkową elastyczność.

awk 'NR == FNR { a[$0]; next } !($0 in a)' nodes_to_keep nodes_to_delete 

Być może, na przykład, chcesz tylko zobaczyć różnicę w liniach, które reprezentują liczby nieujemne:

awk -v r='^[0-9]+$' 'NR == FNR && $0 ~ r { 
    a[$0] 
    next 
} $0 ~ r && !($0 in a)' nodes_to_keep nodes_to_delete 
Powiązane problemy