[gelöst] 2 listen vergleichen ...

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
debianator
Beiträge: 92
Registriert: 24.11.2011 16:30:00

[gelöst] 2 listen vergleichen ...

Beitrag von debianator » 04.02.2012 14:24:08

Hallo Leute,

ich habe hier 2 Listen.

Liste A habe ich selbst erstellt.

Liste B beziehe ich von Quellen im Internet, die diese Liste immer aktuell halten.

Einmal im Monat lade ich die aktuelle Liste B aus dem Internet und füge sie zusammen mit Liste A in eine .txt.

Dann führe ich folgendes Commando aus und als Ergebniss habe ich die ultimative Liste, die ich dann anwende:

Code: Alles auswählen

sort -f ./my_gurus.txt.bak | uniq > ./my_gurus.txt

Das Problem ist nun das Liste A mittlerweile ziemlich alte, nicht mehr gültige und somit unnötige Einträge enthält, die zu unnötigen Verzögerungen während der Anwendung führen können.

Ich konnte es zwar wenn ich sort -f weglasse mit uniq -u schonmal auf nur einmal vorkommende Zeilen eingegrenzt aber es sind immernoch zu viele Einträge um alle zu prüfen.

Also müsste ich irgendwie aus Liste A nur exakt die Zeilen auszugeben, die in Liste B nicht vorkommen, damit ich nur diese näher überprüfen kann.

Aber wie macht man sowas?
Zuletzt geändert von debianator am 06.02.2012 21:21:12, insgesamt 3-mal geändert.

Benutzeravatar
ip
Beiträge: 347
Registriert: 16.05.2007 06:24:04

Re: 2 listen vergleichen ...

Beitrag von ip » 04.02.2012 14:32:56

hi,

guck mal unter
mfg
-ip-
201201-XEN/KVM/NX/Asterisk/Desktop:Debian Squeeze/Kernel 3.1.9/2.6.3x...HW-Raid...ATI/NVidia...xfce/lxde/kde/gdm

Der weg zur Hölle ist mit guten Vorsätzen gepflastert, nicht mit schlechten.
(George Bernard Shaw, * 26.06.1856, Dublin, Irland, † 02.11.1950, Ayot St. Lawrence (Hertford))

debianator
Beiträge: 92
Registriert: 24.11.2011 16:30:00

Re: 2 listen vergleichen ...

Beitrag von debianator » 05.02.2012 17:50:39

Diff kenne ich schon aber da komme ich auch auf mehrere Tausende Zeilen in der Ausgabe.

Das kann ich unmöglich alles nachprüfen.

Ich müsste es irgendwie schaffen das Liste A nur exakt die Zeilen ausgeben werden, die in Liste B nicht vorkommen.

Dann werden das nur ein paar Hundert Zeilen sein.

Hat niemand eine Idee?

lemak
Beiträge: 1213
Registriert: 09.11.2007 13:25:57
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von lemak » 05.02.2012 18:15:55

Ich müsste es irgendwie schaffen das Liste A nur exakt die Zeilen ausgeben werden, die in Liste B nicht vorkommen.
Ich antworte mal wie in Jeopardy :-)

Code: Alles auswählen

$ whatis comm
comm (1)             - Zwei sortierte Dateien Zeile für Zeile vergleichen
up

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von Meillo » 05.02.2012 19:00:04

up hat geschrieben:
Ich müsste es irgendwie schaffen das Liste A nur exakt die Zeilen ausgeben werden, die in Liste B nicht vorkommen.
Ich antworte mal wie in Jeopardy :-)

Code: Alles auswählen

$ whatis comm
comm (1)             - Zwei sortierte Dateien Zeile für Zeile vergleichen
Ha! Das genau waere auch meine Antwort ... aeh Frage ... gewesen. ;-)

Comm(1) ist das passende Tool, wenn es auch fast vergessen ist.
Use ed once in a while!

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: 2 listen vergleichen ...

Beitrag von rendegast » 06.02.2012 06:08:01

Code: Alles auswählen

grep [-v] -f listeB listeA
sollte das tun,
ABER
der Vorgang ist selbst bei ein paar (dutzend) Einträgen extrem rechenaufwändig,
Bsp. wsusoffline rödelt immer auf diesen Stellen herum:

Code: Alles auswählen

$ egrep "grep.*[-]f" wsusoffline70/sh/DownloadUpdates.sh
           grep -i -v -f ../exclude/ExcludeList-SPs.txt $static1 > ../temp/StaticUrls-${sys_old}-${lang}.txt
                grep -i -v -f ../exclude/ExcludeList-SPs.txt $static2 > ../temp/StaticUrls-${sys_old}-${lang}.txt
           grep -i -v -f ../exclude/ExcludeList-SPs.txt $static1 > ../temp/StaticUrls-${sys_old}-glb.txt
                grep -i -v -f ../exclude/ExcludeList-SPs.txt $static2 > ../temp/StaticUrls-${sys_old}-glb.txt
         grep -i -v -f ../exclude/ExcludeList-SPs.txt $static1 > ../temp/StaticUrls-${sys}-${lang}.txt
                grep -i -v -f ../exclude/ExcludeList-SPs.txt $static2 > ../temp/StaticUrls-${sys}-${lang}.txt
grep -F -f ../temp/SupersedingRevisionIds.txt ../temp/ValidUpdateRevisionIds.txt >> ../temp/ValidSupersedingRevisionIds.txt
grep -F -f ../temp/ValidSupersedingRevisionIds.txt ../temp/SupersededUpdateRelations.txt > ../temp/ValidSupersededUpdateRelations.txt
grep -F -f ../temp/ValidSupersededRevisionIds.txt ../temp/BundledUpdateRelationsAndFileIds.txt > ../temp/SupersededRevisionAndFileIds.txt
grep -F -f ../temp/SupersededFileIdsUnique.txt ../temp/UpdateCabExeIdsAndLocations.txt >> ../temp/SupersededCabExeIdsAndLocations.txt
        grep -i -v -f ../temp/Expiredid-${sys}.txt ../temp/Urls-${sys}-${lang}.txt > ../temp/tmpUrls-${sys}-${lang}.txt
        grep -i -f ../temp/Validid-${sys}.txt ../temp/Urls-${sys}-${lang}.txt >> ../temp/tmpUrls-${sys}-${lang}.txt
        grep -i -v -f ../temp/tmpExcludeList-${sys}.txt ../temp/tmpUrls-${sys}-${lang}.txt > ../temp/ValidUrls-${sys}-${lang}.txt
                grep -i -f ../temp/Validid-${sys}.txt ../temp/Urls-${sys}-glb.txt > ../temp/tmpValidUrls-${sys}-glb.txt
                grep -i -v -f ../temp/Expiredid-${sys}.txt ../temp/Urls-${sys}-glb.txt >> ../temp/tmpValidUrls-${sys}-glb.txt
        grep -i -v -f ../temp/tmpExcludeList-${sys}.txt ../temp/tmpValidUrls-${sys}-glb.txt > ../temp/ValidUrls-${sys}-glb.txt
                grep -i -f ../temp/Validid-${sys}.txt ../temp/Urls-${sys}-glb.txt > ../temp/tmpValidUrls-${sys}-glb.txt
                grep -i -v -f ../temp/Expiredid-${sys}.txt ../temp/Urls-${sys}-glb.txt >> ../temp/tmpValidUrls-${sys}-glb.txt
        grep -i -v -f ../temp/tmpExcludeList-${sys}.txt ../temp/tmpValidUrls-${sys}-glb.txt > ../temp/ValidUrls-${sys}-glb.txt
        grep -i -v -f ../temp/tmpExcludeList-win-x86.txt ../temp/Urls-win-x86-${lang}.txt > ../temp/ValidUrls-win-x86-${lang}.txt
  grep -F --file=../temp/OfficeFileIds.txt ../temp/UpdateCabExeIdsAndLocations.txt > ../temp/OfficeUpdateCabExeIdsAndLocations.txt
    grep -F -i -v -f ../temp/ExcludeList-${sys}.txt ../temp/DynamicDownloadLinks-${sys}-${lang}.txt > ../temp/ValidDynamicLinks-${sys}-${lang}.txt
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

uname
Beiträge: 12414
Registriert: 03.06.2008 09:33:02

Re: 2 listen vergleichen ...

Beitrag von uname » 06.02.2012 08:56:02

egrep "grep.*[-]f" wsusoffline70/sh/DownloadUpdates.sh
Was willst du denn damit überhaupt erreichen? Die grep-Suche sollte doch nur einzelne Dateien durchsuchen.

Ich habe mal vor einiger Zeit ein Perl-Script geschrieben. Das Programm liest jede Zeile beider Dateien ein und baut daraus Hash-Variablen. Am Ende werden die Unterschiede beider Dateien oder auch nur eine Datei zur anderen ausgegeben. Die Software ist nicht gerade speichersparend geschrieben, so dass es bei einigen Millionen Zeilen zu Speicherproblemen kommen kann.

http://nopaste.debianforum.de/36226

Code: Alles auswählen

chmod 755 diff.pl

Code: Alles auswählen

./diff.pl datei1 datei2  (Ausgabe aller Unterschiede mit Namen zur Kennzeichnung)

Code: Alles auswählen

./diff.pl datei1 datei2 datei1 (Ausgabe Unterschiede nur von datei1 nicht von datei2)
./diff.pl datei1 datei2 datei2 (Ausgabe Unterschiede nur von datei2 nicht von datei1)
Anmerkung:
Der Software ist es egal ob eine Zeile mehrfach vorkommt. Kommt eine Zeile in einer Datei einmal und in der anderen zweimal vor so gibt es keine Abweichung. Auch wird die Zeilenreihenfolge nicht beachtet.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von Meillo » 06.02.2012 10:21:48

rendegast hat geschrieben:

Code: Alles auswählen

grep [-v] -f listeB listeA
sollte das tun,
ABER
der Vorgang ist selbst bei ein paar (dutzend) Einträgen extrem rechenaufwändig, [...]
uname hat geschrieben: Ich habe mal vor einiger Zeit ein Perl-Script geschrieben. Das Programm liest jede Zeile beider Dateien ein und baut daraus Hash-Variablen. Am Ende werden die Unterschiede beider Dateien oder auch nur eine Datei zur anderen ausgegeben. Die Software ist nicht gerade speichersparend geschrieben, so dass es bei einigen Millionen Zeilen zu Speicherproblemen kommen kann.
Ich frage mich, weshalb noch aufwendige und gleichzeitig eingeschraenkte Loesungsvorschlaege gemacht werden, wo das Problem mit dem einfachen Tool comm(1) (das in POSIX und demnach ueberall verfuegbar ist) schon laengst geloest ist. Zumindest sehe ich keine bedeutende Verbesserung gegenueber dem Ansatz mit comm.
uname hat geschrieben: Anmerkung:
Der Software ist es egal ob eine Zeile mehrfach vorkommt. Kommt eine Zeile in einer Datei einmal und in der anderen zweimal vor so gibt es keine Abweichung. Auch wird die Zeilenreihenfolge nicht beachtet.
Gut, fuer comm will man meistens `sort -u' auf die Eingangsdateien anwenden. Aber soweit war der Fragende ja schon.
Use ed once in a while!

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: 2 listen vergleichen ...

Beitrag von rendegast » 06.02.2012 10:37:11

Meillo hat geschrieben: Ich frage mich, weshalb noch
Weitere Möglichkeiten.



uname hat geschrieben: egrep "grep.*[-]f" wsusoffline70/sh/DownloadUpdates.sh
Was willst du denn damit überhaupt erreichen?
Nur ein Beispiel des grep-Konstrukts in einer Anwendung.
Für das eigentliche Threadproblem war 'grep [-v] -f listeB listeA'.

Die "Performace" des Konstrukts:

Code: Alles auswählen

$ time ls -1 /var/lib/dpkg/info/
...

real    0m0.109s
user    0m0.012s
sys     0m0.020s
$ time ls -1 /var/lib/dpkg/info/ | grep -v -f /etc/fstab 

real    0m2.400s
user    0m2.396s
sys     0m0.016s
$ time ls -1 /var/lib/dpkg/info/ | grep -o -f /etc/fstab 

real    0m8.912s
user    0m8.909s
sys     0m0.020s
zeigt, daß am Tool grep noch Verbesserungsbedarf besteht
(Vielleicht zumindest ein Hinweis in der Manpage über den in diesem Fall schlechten Algorithmus?).
Oder in gewissen Fällen die Daten einer Vorbereitung bedürfen.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: 2 listen vergleichen ...

Beitrag von pferdefreund » 06.02.2012 10:51:49

Beide Listen als Tabellen in ne mysql oder postgresql-DB laden und mit select ... where not exists... auswerten.
Wird wohl am schnellsten gehen, insbesondere, wenn es möglich sein sollten, nen Index zu verwenden. Aber selbst ohne ist
hier ne relationale DB -zumindest für mich - die einfachste Lösung.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von Meillo » 06.02.2012 11:04:43

rendegast hat geschrieben:
Meillo hat geschrieben: Ich frage mich, weshalb noch
Weitere Möglichkeiten.
Leider fehlt ihnen IMO entweder Eleganz oder Mehrwert.

Die "Performace" des Konstrukts:

Code: Alles auswählen

$ time ls -1 /var/lib/dpkg/info/ | grep -v -f /etc/fstab 

real    0m2.400s
user    0m2.396s
sys     0m0.016s
$ time ls -1 /var/lib/dpkg/info/ | grep -o -f /etc/fstab 

real    0m8.912s
user    0m8.909s
sys     0m0.020s
zeigt, daß am Tool grep noch Verbesserungsbedarf besteht
Ich verstehe nicht, weshalb du `grep -o' gegen `grep -v' vergleichst. Zudem enthaelt die fstab ja gar keine sinnvollen Patterns und wenn dann waeren es feste Strings und keine Patterns -> fgrep.


(Vielleicht zumindest ein Hinweis in der Manpage über den in diesem Fall schlechten Algorithmus?).
Ich glaube bevor man hier urteilen kann, sollte man erst in der Sprachentheorie fit sein und dann die konkreten Implementierungen nach ihnen Automatentypen unterscheiden (NFA, DFA, gemischt). Fuer den zweiten Teil kann ich Friedls ``Mastering Regular Expressions'' empfehlen. Fuer die Theorie gibt's zum Beispiel ``Einfuehrung in die Automatentheorie, Formale Sprachen und Komplexitaetstheorie'' von Hopcroft und Ullman. Danach koennen wir uns ueber den Hinweis in der Manpage unterhalten. ;-)


Ich sehe schon, wir schweifen ab und eigentlich sollte ich besser was Sinnvolles arbeiten ....
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von Meillo » 06.02.2012 11:12:48

pferdefreund hat geschrieben:Beide Listen als Tabellen in ne mysql oder postgresql-DB laden und mit select ... where not exists... auswerten.
Wird wohl am schnellsten gehen, insbesondere, wenn es möglich sein sollten, nen Index zu verwenden.
Will das jemand gegen den comm-Ansatz messen?

Code: Alles auswählen

sort -u list-a >list-a.sorted
sort -u list-b >list-b.sorted
comm -1 list-?.sorted
Ich glaube der Vergleich und die Abfrage werden in der Datenbank richtig schnell sein. Aber wie schnell ist das Einfuegen und das Erzeugen des Indexes? (Zudem das Anlegen der Tabelle.)

Ich bin ehrlich an Zahlen interessiert.
Use ed once in a while!

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: 2 listen vergleichen ...

Beitrag von rendegast » 06.02.2012 12:36:13

@Meillo
Meilo hat geschrieben: Ich verstehe nicht, weshalb du `grep -o' gegen `grep -v' vergleichst.
Ich habe einfach ~ 4300 Zeilen (ls dpkg/info/) gegen ~ 200 Zeilen Patternfile (fstab) verglichen.
Der Vergleich sollte keine Ausgabe erzeugen, darum ging es nicht.
Nur darum, daß grep hier bis zu 9 Sekunden herumrechnet (2.9GHz).
Zudem enthaelt die fstab ja gar keine sinnvollen Patterns und wenn dann waeren es feste Strings und keine Patterns -> fgrep.
Das ist natürlich großartig und löst das Problem. Nicht dran gedacht.
In einigen Fällen verwendet wsusoffline ja 'grep -F -f ...' (fgrep),
aber in anderen Fällen nicht, und die sind rechenintensiv.

Damit ist

Code: Alles auswählen

fgrep [-v] -f listeB listeA
doch das eleganteste (wenn es die Daten erlauben)?
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: 2 listen vergleichen ...

Beitrag von Meillo » 06.02.2012 14:05:19

rendegast hat geschrieben:
Meilo hat geschrieben: Ich verstehe nicht, weshalb du `grep -o' gegen `grep -v' vergleichst.
Ich habe einfach ~ 4300 Zeilen (ls dpkg/info/) gegen ~ 200 Zeilen Patternfile (fstab) verglichen.
Der Vergleich sollte keine Ausgabe erzeugen, darum ging es nicht.
Nur darum, daß grep hier bis zu 9 Sekunden herumrechnet (2.9GHz).
Ist ja auch klar, denn grep muss unglaublich viel Arbeit tun. Wenn ein Algorithmus eine quadratische Laufzeit hat, dann ist sie eben quadratisch. ;-)

In deinem Beispiel sind's 4300*200 Vergleiche, falls kein Suchstring vorkommt. Sonst sind's immer noch durchschnittlich 4300*100 Vergleiche.

Bei zwei Listen mit jeweils n=4300 unsortierten Zeilen. Kommen wir mit `fgrep -f' auf eine Laufzeit von rund: n*(n/2) = 4300*2150 = 9.245.000 Operationen. Mit 2x sort und comm sind es rund: 2 * (n*log(n)) + n = 2 * (4300*3.6) + 4300 = 35.547 Operationen. Man kann das zwar nicht so einfach rechnen, aber ich glaube man bekommt eine grobe Vorstellung um welche Groessenordnungen es geht. Fachleute auf diesem Gebiet moegen mich verbessern und belehren.

Code: Alles auswählen

fgrep [-v] -f listeB listeA
doch das eleganteste (wenn es die Daten erlauben)?
Was ist mit Teilmatches? In Liste B gibt es eine Zeile die *in* einer Zeile in Liste A auftaucht? Man muesste alles an Zeilenanfang und -ende ankern.

Fuer den User mag diese Anweisung einfach zu tippen sein, aber die von fgrep getane Arbeit ist IMO nicht elegant.

Trotzdem danke fuer die Idee, auf die ich bisher noch nicht gekommen bin. Ich werde sie in mein Repertoire aufnehmen. ;-)
Use ed once in a while!

debianator
Beiträge: 92
Registriert: 24.11.2011 16:30:00

Re: 2 listen vergleichen ...

Beitrag von debianator » 06.02.2012 21:17:55

Achja genau, Teilmatches hatte ich auch noch aber die diff.pl ist wie massgeschneidert, vielen Dank dafür.

Antworten