Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[bash] Sortieren von Inhalten in Dateien
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Diskussionsforum
View previous topic :: View next topic  
Author Message
3PO
Veteran
Veteran


Joined: 26 Nov 2006
Posts: 1110
Location: Schwabenländle

PostPosted: Thu Apr 01, 2010 9:03 am    Post subject: [bash] Sortieren von Inhalten in Dateien Reply with quote

Hallo Zusammen,

ich habe mal wieder ein kleines Problen, was das filtern von Dateien angeht. :)

Ich habe eine Datei, index.txt, die sieht z.B. so aus:

Code:
Anton müller
Ärger
Berta Maier
Cäsar
Charlotte berger
Dora


Nun habe ich eine 2te Datei, liste.txt und eine 3te Datei, out.txt.

So, nun das Problem:

Ich möchte nun liste.txt durchsuchen und nur die Zeilen, die Worte enthalten, die in der index.txt stehen sollen in die out.txt geschrieben werden.
Ein weiteres Problem ist, dass die Groß/Kleinschreibung ignoriert werden soll. D.h. das z.B. auch Zeilen die anton und berta enthalten, nach out.txt geschrieben werden sollen.

Ich stehe gerade auf dem Schlauch und finde keinen Ansatz.
Evtl. hat ja hier Jemand eine Idee? :)
Back to top
View user's profile Send private message
toj
n00b
n00b


Joined: 19 Sep 2005
Posts: 13

PostPosted: Thu Apr 01, 2010 1:09 pm    Post subject: Reply with quote

so ungefähr könntes es gehen:

Code:
while read line; do
      for word in $line ; do
            if grep -iq "$word" ./index.txt ; then
                  echo "Treffer: $line"
            fi
      done
done<./liste.txt
Back to top
View user's profile Send private message
toralf
Developer
Developer


Joined: 01 Feb 2004
Posts: 3943
Location: Hamburg

PostPosted: Thu Apr 01, 2010 2:50 pm    Post subject: Reply with quote

Etwas in dieser Art
Code:
grep -i -e $(cat index.txt | xargs | sed 's/ / -e /g') liste.txt > out.txt
geht auch (meistens).
Back to top
View user's profile Send private message
Necoro
Veteran
Veteran


Joined: 18 Dec 2005
Posts: 1912
Location: Germany

PostPosted: Thu Apr 01, 2010 3:05 pm    Post subject: Reply with quote

toralf wrote:
Etwas in dieser Art
Code:
grep -i -e $(cat index.txt | xargs | sed 's/ / -e /g') liste.txt > out.txt
geht auch (meistens).

Ich würde dem grep noch ein "-w" mitgeben um nur ganze Worte zu matchen
_________________
Inter Deum Et Diabolum Semper Musica Est.
Back to top
View user's profile Send private message
3PO
Veteran
Veteran


Joined: 26 Nov 2006
Posts: 1110
Location: Schwabenländle

PostPosted: Thu Apr 01, 2010 3:07 pm    Post subject: Reply with quote

Thx @ toj & toralf,

das funktioniert soweit schon ganz gut, allerdings habe ich ein kleines Problem:

wenn nun in der liste.txt z.B. "Bergdorf" steht und und der index.txt,

Code:
....
berg
Dorf
....


steht, dann wird die Zeile trotzdem in die out.txt geschrieben.

Das sollte aber nicht sein.

Gibt es dafür auch eine Lösung?
Back to top
View user's profile Send private message
toralf
Developer
Developer


Joined: 01 Feb 2004
Posts: 3943
Location: Hamburg

PostPosted: Thu Apr 01, 2010 3:26 pm    Post subject: Reply with quote

3PO wrote:
Gibt es dafür auch eine Lösung?
Klar, siehe Necoro:
Code:
grep -i -w ...
Back to top
View user's profile Send private message
3PO
Veteran
Veteran


Joined: 26 Nov 2006
Posts: 1110
Location: Schwabenländle

PostPosted: Thu Apr 01, 2010 3:39 pm    Post subject: Reply with quote

grep -iew nimmt aber auch "bergdorf" wenn in der index.txt z.B. "Berg Dorf" steht.

Ich brächte halt einen Parameter der die komplette Zeile nimmt, so wie sie ist.
Back to top
View user's profile Send private message
Necoro
Veteran
Veteran


Joined: 18 Dec 2005
Posts: 1912
Location: Germany

PostPosted: Thu Apr 01, 2010 3:43 pm    Post subject: Reply with quote

das w muss schon vor dem e stehen ...

/edit: info grep hat noch nie geschadet :) *dir als Bettlektüre empfehl*
_________________
Inter Deum Et Diabolum Semper Musica Est.
Back to top
View user's profile Send private message
toralf
Developer
Developer


Joined: 01 Feb 2004
Posts: 3943
Location: Hamburg

PostPosted: Thu Apr 01, 2010 4:01 pm    Post subject: Reply with quote

3PO wrote:
grep -iew nimmt aber auch "bergdorf" wenn in der index.txt z.B. "Berg Dorf" steht.
Natürlich, und vermutlich auch jedes andere Wort, in dem ein "w" oder "W" vorkommt ...
Back to top
View user's profile Send private message
3PO
Veteran
Veteran


Joined: 26 Nov 2006
Posts: 1110
Location: Schwabenländle

PostPosted: Thu Apr 01, 2010 4:15 pm    Post subject: Reply with quote

Necoro wrote:
das w muss schon vor dem e stehen ...

/edit: info grep hat noch nie geschadet :) *dir als Bettlektüre empfehl*


info grep und man grep kenne ich natülich und habe es auch gelesen. Evtl ist ja grep auch nicht das optimale Tool für das was ich vorhabe?

Seltsam ist halt, dass wenn ich grep -i "berg dorf" liste.txt mache, dann erhalte ich das gewünschte Ergebnis.

Jetzt ist halt die Frage, wie ich das in ein Scrpit packe, damit eben ganze Zeilen genommen werden und nicht nur einzelne Worte einer Zeile?
Back to top
View user's profile Send private message
ScytheMan
l33t
l33t


Joined: 30 Nov 2005
Posts: 605

PostPosted: Thu Apr 01, 2010 5:31 pm    Post subject: Reply with quote

Ohne den Thread jetzt hijacken zu wollen, mit einer Diskussion was besser/schlechter ist, aber aus Interesse mal folgende Frage:
Wieso nimmt man dafür "Shelltools" und keine Skriptsprache á la Python, Ruby oder Perl?
Zu miese Performance? Nicht geekig genug?
Back to top
View user's profile Send private message
3PO
Veteran
Veteran


Joined: 26 Nov 2006
Posts: 1110
Location: Schwabenländle

PostPosted: Thu Apr 01, 2010 6:52 pm    Post subject: Reply with quote

ScytheMan wrote:
[...] Wieso nimmt man dafür "Shelltools" und keine Skriptsprache á la Python, Ruby oder Perl? ...


"Man" nimmt kein Python, Ruby oder Perl, weil "man" eben kein Python, Ruby oder Perl kann.

Außderdem ist ist das ja nur ein Teil eines Scriptes und der Rest geht ja schon.
Back to top
View user's profile Send private message
ScytheMan
l33t
l33t


Joined: 30 Nov 2005
Posts: 605

PostPosted: Thu Apr 01, 2010 8:27 pm    Post subject: Reply with quote

3PO wrote:
ScytheMan wrote:
[...] Wieso nimmt man dafür "Shelltools" und keine Skriptsprache á la Python, Ruby oder Perl? ...


"Man" nimmt kein Python, Ruby oder Perl, weil "man" eben kein Python, Ruby oder Perl kann.

Außderdem ist ist das ja nur ein Teil eines Scriptes und der Rest geht ja schon.


Ok, das ist eine Erklärung. Hoffe du hast das "man" nicht in den falschen Hals gekriegt, war nicht abwertend oder so gemeint. Hab es unpersönlich belassen, weil ja nicht nur du gepostet hattest sondern auch andre ;)

Generell bin ich trotzdem noch an meiner Frage interessiert: Wie sieht die Performance Shell vs. "Skriptsprache" aus?
Back to top
View user's profile Send private message
Necoro
Veteran
Veteran


Joined: 18 Dec 2005
Posts: 1912
Location: Germany

PostPosted: Thu Apr 01, 2010 8:31 pm    Post subject: Reply with quote

ScytheMan wrote:
Generell bin ich trotzdem noch an meiner Frage interessiert: Wie sieht die Performance Shell vs. "Skriptsprache" aus?

Ich ignorier jetzt mal die Frage nach der Performance, sondern gehe nur auf die Schwierigkeit des Codens ein...

Also in Perl kann ich mir vorstellen, dass die Aufgabe sehr schnell gelöst ist ... in Python wirds schon schwieriger. Am Ende halte ich das zu Skripten denn doch für einfacher (ist ja nur n Einzeiler) ... und bei komplizierterem kann man denn awk verwenden.
_________________
Inter Deum Et Diabolum Semper Musica Est.
Back to top
View user's profile Send private message
mv
Watchman
Watchman


Joined: 20 Apr 2005
Posts: 6780

PostPosted: Sun Apr 04, 2010 2:28 pm    Post subject: Reply with quote

ScytheMan wrote:
Wieso nimmt man dafür "Shelltools" und keine Skriptsprache á la Python, Ruby oder Perl?
Zu miese Performance?

Nein, ganz im Gegenteil: Die Shell-Lösungen für ein nicht ganz triviales Problem wie dieses hier haben eine grausame Performance. Quadratische Laufzeit :roll: (falls index.txt Kilobytes lange ist, kann man alle bisherigen Shell-Lösungen in der Pfeife rauchen; die einzige effiziente Lösung mit dem Aufbauen eines komplexen grep-Ausdrucks wird dann an der maximalen Kommandozeilenlänge scheitern). So etwas sollte man höchstens dann in Shell skripten, wenn es wegen der Kompatibilität unbedingt erforderlich ist. Ansonsten ist die Aufgabe in typisches Problem, für das Perl geschaffen wurde.
Code:
#! /usr/bin/env perl
use strict;
use warnings;
my($index,$liste,$output,@A);
open($index, "<", "index.txt") or die "cannot read index.txt";
while(<$index>) { chomp; s/(\W)/\\$1/g; push (@A, qr/\b$_\b/i) }
close($index);

open($liste, "<", "liste.txt") or die "cannot read liste.txt";
open($output, ">", "output.txt") && select($output)
   or die "cannot write to output.txt";
while(<$liste>) {
   for my $match (@A) {
      if(/$match/) { print; last }
   }
}
Zugegeben: Ist länger als die obigen Lösungen, enthält aber auch Vieles was eigentlich nicht notwendig ist (use strict/warnings, Fehlerabfragen).
Im Gegensatz zu den vorherigen Lösungen ist es die einzige, die mit Sonderzeichen in "index.txt" korrekt umgeht. Außerdem skaliert es vernünftig, und bei Bedarf kann man an der quadratischen Laufzeit basteln, indem man ein assoziatives Array statt eines "normalen" Arrays aus regular expressions benutzt.
Back to top
View user's profile Send private message
toj
n00b
n00b


Joined: 19 Sep 2005
Posts: 13

PostPosted: Mon Apr 05, 2010 9:35 am    Post subject: Reply with quote

Code:
grep -i -e $(cat index.txt | xargs | sed 's/ / -e /g') liste.txt > out.txt
finde ich ziemlich elegant im Vergleich zu meinem Vorschlag; wegen des nur einmaligen grep Aufrufs wird das auch wesentlich schneller sein.

@mv: Wo siehst du denn eine Laufzeit O(n^2)? Das Problem ist ein lineares (O(n)),[/quote] und zwar unabhängig von der verwendeten Sprache.
Back to top
View user's profile Send private message
mv
Watchman
Watchman


Joined: 20 Apr 2005
Posts: 6780

PostPosted: Mon Apr 05, 2010 5:26 pm    Post subject: Reply with quote

toj wrote:
@mv: Wo siehst du denn eine Laufzeit O(n^2)?

Für jede Zeile in liste.txt (sagen wir: Länge n) wird jede Zeile in index.txt (sagen wir: ebenfalls Länge n) einmal überprüft. Macht n*n Überprüfungen. Außer bei der Perl-Lösung und der Lösung mit dem einzelnen grep-Aufruf (bei dem es aber dafür wie erwähnt die Probleme mit der Kommandozeilenbegrenzung gibt), findet die Überprüfung nicht einmal im Speicher sondern nur auf Disk (bestenfalls im Kernel Disk-Cache) statt.
Immerhin wäre es möglich, die Laufzeit auf O(n*log n) zu drücken (oder falls man genügend Speicher und genügend gute Hashes voraussetzt sogar auf O(n)).
Back to top
View user's profile Send private message
mv
Watchman
Watchman


Joined: 20 Apr 2005
Posts: 6780

PostPosted: Mon Apr 05, 2010 5:52 pm    Post subject: Reply with quote

Um klarzumachen, was ich mit linearer Laufzeit meine, hier ist die Perl-Version dafür:
Code:
#! /usr/bin/env perl
use strict;
use warnings;
open(INDEX, "<", "index.txt") or die "cannot read index.txt";
my %A=(); while(<INDEX>) { chomp; $A{lc $_}=1; }
close INDEX;

open(LISTE, "<", "liste.txt") or die "cannot read liste.txt";
open(OUTPUT, ">", "output.txt") && select(OUTPUT)
   or die "cannot write to output.txt";
while(<LISTE>) {
   for my $i (split) {
      if(exists $A{lc $i}) { print; last }
   }
}

Etwas vergleichbar Effizientes ist mit Shell-Mitteln kaum zu machen.
OK: Einige Shells wie zsh oder neuerdings auch Bash können ebenfalls Hashes und haben vielleicht auch interne Kommandos um so etwas wie "lowercase" zu liefern; trotzdem ist eine Shell einfach nicht die richtige Sprache für so etwas (und dürfte auch weitaus ineffizienter sein).
Back to top
View user's profile Send private message
toj
n00b
n00b


Joined: 19 Sep 2005
Posts: 13

PostPosted: Tue Apr 06, 2010 12:09 am    Post subject: Reply with quote

mv wrote:
toj wrote:
@mv: Wo siehst du denn eine Laufzeit O(n^2)?

Für jede Zeile in liste.txt (sagen wir: Länge n) wird jede Zeile in index.txt (sagen wir: ebenfalls Länge n) einmal überprüft. Macht n*n Überprüfungen.

Das ist falsch. Die Größe des Problems wird ausschließlich durch die Länge der Liste beschrieben (für jedes Element entscheide ob Topf A oder B). Da die Entscheidung nicht abhängig von der Größe des Problems ist, ist der Index in diesem Zusammenhang irrelevant. Für die konkrete Laufzeit ist der Index natürlich nicht irrelevant: Je nachdem wie schnell die Entscheidung getroffen wird (wie gut der Index bzw. der Algorithmus der Entscheidung ist) desto besser oder schlechter ist die Geschwindigkeit des Programms. Nur: Wenn einmal festgelegt, bleibt die Art der Entscheidung immer die gleiche, egal wie groß oder klein das Problem wird.

Aber was mir eigentlich wichtiger ist: Die Laufzeitkomplexität eines Algorithmus ist nicht abhängig von einer Programmiersprache. Mit jeder kann man mehr oder weniger geschickt vorgehen, einige eignen sich für ein konkrete Problem besser oder weniger gut als andere ... aber der Algorithmus ist im Vergleichsfall der selbe.
Back to top
View user's profile Send private message
mv
Watchman
Watchman


Joined: 20 Apr 2005
Posts: 6780

PostPosted: Tue Apr 06, 2010 12:15 pm    Post subject: Reply with quote

toj wrote:
mv wrote:
toj wrote:
@mv: Wo siehst du denn eine Laufzeit O(n^2)?

Für jede Zeile in liste.txt (sagen wir: Länge n) wird jede Zeile in index.txt (sagen wir: ebenfalls Länge n) einmal überprüft. Macht n*n Überprüfungen.

Das ist falsch. Die Größe des Problems wird ausschließlich durch die Länge der Liste beschrieben

Nope. Bei der Messung von Laufzeit von Algorithmen nimmt man selbstverständlich die gesamten Daten (hier: Liste+Index) und darf nicht einfach annehmen, dass bei Wachsen der Daten ausschließlich die Liste wächst und nicht der Index. Ansonsten wäre Index kein Teil der Daten, sondern fest, und könnte damit als Teil des Algorithmus aufgefasst werden - das würde ein anderes Problem lösen
Quote:
Aber was mir eigentlich wichtiger ist: Die Laufzeitkomplexität eines Algorithmus ist nicht abhängig von einer Programmiersprache

Das ist so pauschal nicht richtig; die Laufzeitkomplexität hängt i.d.R. davon ab, welche Operationen man in konstanter Zeit durchführen kann. Wenn man beispielsweise in einer Sprache arbeitet, die keinen "random access" auf Arrays erlaubt, bei der also ein Zugriff auf ein Array linear mit der Arraylänge wächst (wie bei POSIX Shell), ist man halt prinzipiellen Einschränkungen unterworfen. Mal abgesehen davon, dass im Fall riesiger Konstanten (wie ebenfalls bei Shell, wo man ev. Dinge in Files erledigen muss, die bei anderen Sprachen im Speicher ablaufen) nicht nur die Komplexität alleine das Entscheidende ist.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Diskussionsforum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum