mit grep einen Block von Zeilen anzeigen
Hallo, ich habe hier ein Textfile das folgendermaßen formatiert ist: #################### Text Zeile 1 Text Zeile 2 Text Zeile 3 Text Zeile 4 ... Text Zeile n #################### Text Zeile 1 ... Text Zeile n #################### ... Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. Mit grep kann ich jetzt wunderbar suchen und auch bestimmen welche Zeilen angezeigt werden. z.B. mit grep -5 'meinSuchtext' meinTestfile.txt jeweils 5 Zeilen vor und nach der Fundstelle anzeigen. Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind. Geht das mit grep? Oder mit einem anderen Programm? Danke für jeden Hinweis. Wolfgang -- www.golder.de
Am Montag, 28. August 2006 09:44 schrieb Wolfgang Golder:
ich habe hier ein Textfile das folgendermaßen formatiert ist:
#################### Text Zeile 1 Text Zeile 2 Text Zeile 3 Text Zeile 4 ... Text Zeile n #################### Text Zeile 1 ... Text Zeile n #################### ...
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. Mit grep kann ich jetzt wunderbar suchen und auch bestimmen welche Zeilen angezeigt werden. z.B. mit grep -5 'meinSuchtext' meinTestfile.txt jeweils 5 Zeilen vor und nach der Fundstelle anzeigen.
Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind.
Geht das mit grep? Oder mit einem anderen Programm?
für solche die's gerne kompliziert mögen, geht das sicherlich mit sed. Ansonsten würde ich das mit awk oder perl machen. mit grep geht das (meines Wissens nach) nicht. Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Hallo Jürgen, On Montag 28 August 2006 10:20 wrote Dr. Jürgen Vollmer:
für solche die's gerne kompliziert mögen, geht das sicherlich mit sed. Ansonsten würde ich das mit awk oder perl machen. mit grep geht das (meines Wissens nach) nicht.
schade, daß das nicht einfach geht :-( Die Wichtigkeit ist aber nicht so hoch, als daß ich dafür eine der von dir genannten Möglichkeiten _lernen_ würde. Da es sich nur um die aufbereiteten Texte der internen Mailbox eines Online Spieles handelt werde ich halt mit grep weitermachen. Danke Wolfgang -- www.golder.de
Am Dienstag, 29. August 2006 15:00 schrieb Wolfgang Golder:
Hallo Jürgen,
On Montag 28 August 2006 10:20 wrote Dr. Jürgen Vollmer:
für solche die's gerne kompliziert mögen, geht das sicherlich mit sed. Ansonsten würde ich das mit awk oder perl machen. mit grep geht das (meines Wissens nach) nicht.
schade, daß das nicht einfach geht :-( Die Wichtigkeit ist aber nicht so hoch, als daß ich dafür eine der von dir genannten Möglichkeiten _lernen_ würde.
hey awk ist wirklich nicht so schwer! Kennt man' will man' nie wieder missen. Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Am Montag, 28. August 2006 09:44 schrieb Wolfgang Golder:
Hallo, [...] Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. [...] Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind.
Geht das mit grep? Oder mit einem anderen Programm?
Hallo Wolfgang, willst Du das automatisiert machen oder reicht es von Hand die Zeilen zu holen? Wenn die Texte von Hand zu holen: grep -n suchtext datei head -ni datei | tail (nj) ni = Zeilennummer des Blockendes nj = ni - Zeilennummer des Blockanfanges + 1 Kommt Dein Suchtext exakt zweimal vor geht es auch so: grep -A 10000 suchtext datei | grep -B 10000 suchtext Sind Start und Ende des Blockes eindeutig mit einem Suchtext zu beschreiben, geht auch: grep -A 10000 suchtext_start | grep -B 10000 suchtext_ende Wie groß die Zahl nach A oder B werden kann, weiß ich nicht. Bei einer kleinen Datei haben auch 100000 funktioniert. Für das, was nicht dort hinein paßt, hat Jürgen schon alles gesagt. Gued gohn Achim
Hallo Achim, On Montag 28 August 2006 13:21 wrote Joachim Tüns:
willst Du das automatisiert machen oder reicht es von Hand die Zeilen zu holen?
händisch suchen.
Wenn die Texte von Hand zu holen:
Leider passen die von dir genannten Möglichkeiten nicht auf das was ich suche.
Für das, was nicht dort hinein paßt, hat Jürgen schon alles gesagt.
Wie dort geschrieben sind die zu aufwendig. Danke Wolfgang -- www.golder.de
Wolfgang Golder schrieb:
Hallo,
ich habe hier ein Textfile das folgendermaßen formatiert ist:
#################### Text Zeile 1 Text Zeile 2 Text Zeile 3 Text Zeile 4 ... Text Zeile n #################### Text Zeile 1 ... Text Zeile n #################### ...
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. Mit grep kann ich jetzt wunderbar suchen und auch bestimmen welche Zeilen angezeigt werden. z.B. mit grep -5 'meinSuchtext' meinTestfile.txt jeweils 5 Zeilen vor und nach der Fundstelle anzeigen.
Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind.
Geht das mit grep? Oder mit einem anderen Programm?
Danke für jeden Hinweis.
Wolfgang
# print section of file between two regular expressions (inclusive) sed -n '/Iowa/,/Montana/p' # case sensitive Siehe: http://www.student.northpark.edu/pemente/sed/sed1line.txt Gruss Bernd
Am Montag, 28. August 2006 09:44 schrieb Wolfgang Golder:
ich habe hier ein Textfile das folgendermaßen formatiert ist:
#################### Text Zeile 1 Text Zeile 2 Text Zeile 3 Text Zeile 4 ... Text Zeile n #################### Text Zeile 1 ... Text Zeile n #################### ...
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. [...] Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind.
Hallo Wolfgang, ich habe bisher noch nicht sehr viel mir awk gemacht und fand das Problem spannend. Die Aussage der anderen, dass ein solches Problem doch ganz einfach sein sollte, hat den Ehrgeiz geweckt. Bisher hatte ich immer nur das Problem, ab einer definierten Zeile bis zu einer anderen definierten Zeile zu suchen. Du aber möchtest, nachdem Du das Suchwort gefunden hast, den gesamten Block, also auch die Zeilen vor der Zeile mit dem Suchwort ausgegeben haben. Außerdem gibt es bei Dir keine Unterschiedlichen Markierungen für Anfang und Ende. Wenn ich es richtig verstanden habe, hilft Dir auch die von Bernd geschriebene Lösung (sed -n '/Iowa/,/Montana/p) nicht weiter, weil der gesuchte Block eben nicht durch spezielle Anfangs- und Endzeilen sondern durch eine Zeile in der Mitte des Blocks charakterisiert ist. Diese Tatsachen fand ich im ersten Moment erschwerend, aber ich habe folgendes awk-Skript geschrieben: ----- BEGIN { start=0; gefunden=0; inhalt=""; } { if ($0 ~ /####################/ && start==1) { if (gefunden==0) {inhalt="";} else {start=0} } } { if ($0 ~ /####################/ && gefunden==0) { start=1; } else { if (start==1) { inhalt=inhalt $0 "\n"; if ($0 ~ /Suchwort/) { gefunden=1 } } } } END { print inhalt; } ----- Bestimmt geht das noch besser und es hat auch noch einen kleinen Nachteil: Am Ende wird immer eine zusätzliche Leerzeile ausgegeben. Wegen begrenzter Kenntnisse im Zusammenspiel mit Müdigkeit, habe ich das jetzt nicht mehr beseitigt. Gruß, Achim
Am Mittwoch, 30. August 2006 01:07 schrieb Achim Schäfer:
Am Montag, 28. August 2006 09:44 schrieb Wolfgang Golder:
ich habe hier ein Textfile das folgendermaßen formatiert ist:
#################### Text Zeile 1 Text Zeile 2 Text Zeile 3 Text Zeile 4 ... Text Zeile n #################### Text Zeile 1 ... Text Zeile n #################### ...
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. [...] Ich würde aber zu einer Fundstelle immer gerne den gesamten Block zwischen den ###... sehen. Unabhängig davon wieviel Zeilen es sind.
Hallo Wolfgang,
ich habe bisher noch nicht sehr viel mir awk gemacht und fand das Problem spannend. Die Aussage der anderen, dass ein solches Problem doch ganz einfach sein sollte, hat den Ehrgeiz geweckt.
Bisher hatte ich immer nur das Problem, ab einer definierten Zeile bis zu einer anderen definierten Zeile zu suchen. Du aber möchtest, nachdem Du das Suchwort gefunden hast, den gesamten Block, also auch die Zeilen vor der Zeile mit dem Suchwort ausgegeben haben. Außerdem gibt es bei Dir keine Unterschiedlichen Markierungen für Anfang und Ende.
Wenn ich es richtig verstanden habe, hilft Dir auch die von Bernd geschriebene Lösung (sed -n '/Iowa/,/Montana/p) nicht weiter, weil der gesuchte Block eben nicht durch spezielle Anfangs- und Endzeilen sondern durch eine Zeile in der Mitte des Blocks charakterisiert ist.
Diese Tatsachen fand ich im ersten Moment erschwerend, aber ich habe folgendes awk-Skript geschrieben:
----- BEGIN { start=0; gefunden=0; inhalt=""; }
{ if ($0 ~ /####################/ && start==1) { if (gefunden==0) {inhalt="";} else {start=0} } }
{ if ($0 ~ /####################/ && gefunden==0) { start=1; } else { if (start==1) { inhalt=inhalt $0 "\n"; if ($0 ~ /Suchwort/) { gefunden=1 } } } }
END { print inhalt; } -----
Bestimmt geht das noch besser und es hat auch noch einen kleinen Nachteil: Am Ende wird immer eine zusätzliche Leerzeile ausgegeben. Wegen begrenzter Kenntnisse im Zusammenspiel mit Müdigkeit, habe ich das jetzt nicht mehr beseitigt.
awk kennt auch arrays. man spart sich dann die stringkonkatenation, die u.U. doch zeitwendig sein kann. Auch das Problem mit der finalen Leerzeile wird damit vermieden. Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Am Mittwoch, 30. August 2006 09:02 schrieb Dr. Jürgen Vollmer:
awk kennt auch arrays. man spart sich dann die stringkonkatenation, die u.U. doch zeitwendig sein kann. Auch das Problem mit der finalen Leerzeile wird damit vermieden.
Mit ausgeschlafenem Kopf geht das doch alles besser... Die Arrays hatte ich gesehen, hatte mich aber leider verlesen: Ich hatte gelesen, dass man die Größe des Arrays beim Erstellen festlegen muss. Da hatte ich wohl das "nicht" überlesen :-( Danke für den Hinweis. Achim
Am Mittwoch, 30. August 2006 10:40 schrieb Achim Schäfer:
Am Mittwoch, 30. August 2006 09:02 schrieb Dr. Jürgen Vollmer:
awk kennt auch arrays. man spart sich dann die stringkonkatenation, die u.U. doch zeitwendig sein kann. Auch das Problem mit der finalen Leerzeile wird damit vermieden.
Mit ausgeschlafenem Kopf geht das doch alles besser...
Die Arrays hatte ich gesehen, hatte mich aber leider verlesen: Ich hatte gelesen, dass man die Größe des Arrays beim Erstellen festlegen muss.
ne, ne, das sind assoziative arrays, also solche die auch mit stings inidziert werden können (zumindest bei gawk). Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Am Mittwoch, 30. August 2006 10:49 schrieb Dr. Jürgen Vollmer:
Mit ausgeschlafenem Kopf geht das doch alles besser...
Die Arrays hatte ich gesehen, hatte mich aber leider verlesen: Ich hatte gelesen, dass man die Größe des Arrays beim Erstellen festlegen muss.
ne, ne, das sind assoziative arrays, also solche die auch mit stings inidziert werden können (zumindest bei gawk).
Ja, das habe ich jetzt auch gesehen. Und als kleine Übung habe ich das Skript dann doch noch mal mit Arrays geschrieben. s.u. Übrigens, kann mir jemand einen Hinweis zur Verwendung von XEmacs bei awk Skripten geben? Im AWK-Modus verhält er sich nicht so, wie ich mir das wünschen würde: - Beim Tippen von {, } oder ; bekomme ich ebenso wie beim betätigen von Tab einen Piepston mit der Fehlermeldung "Wrong type argument: stringp, nul" Was muss ich tun, damit der Modus vernünftig funktioniert? Hier ist das Skript. Ich bin offen für weitere Verbesserungsvorschläge. ----- BEGIN { start=0; gefunden=0; } # Am Ende eines Blocks wird start zurückgesetzt, wenn Suchwort gefunden { if ($0 ~ /####################/ && start==1 && gefunden==1) { start=0; } } # Am Anfang eines Blocks wird gesammelt, wenn Wort noch nicht gefunden { if ($0 ~ /####################/ && gefunden==0) { start=1; zaehler=0; } else { if (start==1) { inhalt[zaehler]=$0; zaehler++; if ($0 ~ /Suchwort/) { gefunden=1 } } } } END { for (x = 0; x < zaehler; x++) { print inhalt[x] } } ----- Gruß Achim
Am Mittwoch, 30. August 2006 11:27 schrieb Achim Schäfer:
Hier ist das Skript. Ich bin offen für weitere Verbesserungsvorschläge.
anbei meine Version: -------------------- # Am Ende eines Blocks wird start zurückgesetzt, wenn Suchwort gefunden # das if() kann man sich sparen. awk ist eine Regelorientierte Sprache ($0 ~ /####################/ && start==1 && gefunden==1) { start=0; next; # die anderen Muster müssen nicht mehr untersucht werden } # Am Anfang eines Blocks wird gesammelt, wenn Wort noch nicht gefunden ($0 ~ /####################/ && gefunden==0) { start=1; zaehler=0; next; } (start == 1) { inhalt[zaehler]=$0; zaehler++; ## GAWK (vielleicht auch andere) erlauben Variablen als reg. Ausrücke, ## hier also SUCHWORT if ($0 ~ SUCHWORT) { gefunden=1 } } END { for (x = 0; x < zaehler; x++) { print inhalt[x] } } -------- speichert man das Script als foo.awk, dann kann man die Variable SUCHWORT so definierten: awk -f foo.awk -v SUCHWORT=foobar eingabedatei ohne GAWK kann man ähnliches erreichen, wenn man das AWK-Script in ein SH-Script einbettet und etwas mit den Quotes "spielt": in etwa so: ------------ #!/bin/sh SUCHVAR=$1 # hier ist SHELL awk < $DATEI ' ... if ($0 ~ /'$SUCHWORT'/) { ---------------^+++++++++^ hier wird von der SHELL die SHELL-variable --------------- expandiert, bevor AWK gestartet wird ... ' -------------- Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 92 04 87 1 Fax: +49(721) 92 04 87 2 Juergen.Vollmer@informatik-vollmer.de www.informatik-vollmer.de Internet-Telefonie: www.skype.com Benutzer: juergen.vollmer
Hallo, Am Mit, 30 Aug 2006, Dr. Jürgen Vollmer schrieb:
END { for (x = 0; x < zaehler; x++) { print inhalt[x] } }
Also in der manpage steht folgendes: for (var in array) statement Ergo: END { for (s in inhalt) { print s; } }
speichert man das Script als foo.awk, dann kann man die Variable SUCHWORT so definierten:
awk -f foo.awk -v SUCHWORT=foobar eingabedatei
ohne GAWK kann man ähnliches erreichen, wenn man das AWK-Script in ein SH-Script einbettet und etwas mit den Quotes "spielt":
awk kennt eine ARGV Variable. Und schaut mal nach /usr/share/awk! Da findet sich z.B. ein 'getopt.awk' das fuer sowas einfaches aber zu "dick" ist. Hier reicht: BEGIN { SUCHWORT=ARGV[1]; delete ARGV[1]; } [..] ($0 ~ SUCHWORT) { [..Rest vom Script..]
in etwa so: #!/bin/sh SUCHVAR=$1 # hier ist SHELL ^^ Quoten!
awk < $DATEI ' ... if ($0 ~ /'$SUCHWORT'/) { ^^^^^^^^^quoten!
-dnh -- Mary had a little lamb, her father shot it dead. Now she goes to school with it, between two lumps of bread. -- sig of C. Herbig
Hallo Achim, On Mittwoch 30 August 2006 01:07 wrote Achim Schäfer:
Diese Tatsachen fand ich im ersten Moment erschwerend, aber ich habe folgendes awk-Skript geschrieben:
erstmal danke. Ich habe begonnen mich einzulesen und habe dein Skript so verändert, daß ich einen Suchbegriff auf der Kommandozeile übergeben kann. awk -f tg1.awk test.txt 'mein Suchtext' Dann habe ich es noch so geändert, daß mehrere Fundstellen nacheinander angezeigt werden. #!/usr/bin/awk -f BEGIN { start=0; gefunden=0; inhalt=""; Suchtext=ARGV[2] delete ARGV[2] } { if ($0 ~ /####################/ && start==1) # Trennzeile nach Fundstelle { if (gefunden==0) # der Suchtext wurde noch nicht gefunden {inhalt="";} else # Suchtext wurde bereits gefunden { if (inhalt!="") # keine leeren Zeilen anzeigen print inhalt; inhalt=""; # zurücksetzen für evtl. nächste Fundstellen start=0 gefunden=0; } } } { if ($0 ~ /####################/ && gefunden==0) # Trennzeile vor Fundstelle { start=1; # deshalb ist die nächste Trennzeile nach der Fundstelle } else { if (start==1) { inhalt=inhalt $0 "\n"; # inhalt wird um die aktuelle Zeile ergänzt if ($0 ~ Suchtext) # die aktuelle Zeile enthält den Suchtext { gefunden=1 # merken dass Suchtext gefunden wurde } } } } END {} # nichts ausgeben; wurde ja schon oben gemacht Grüße Wolfgang -- www.golder.de
Hallo, Am Mon, 28 Aug 2006, Wolfgang Golder schrieb:
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. Mit grep kann ich jetzt wunderbar suchen und auch bestimmen welche Zeilen angezeigt werden. z.B. mit grep -5 'meinSuchtext' meinTestfile.txt jeweils 5 Zeilen vor und nach der Fundstelle anzeigen.
agrep -d 'TRENNMUSTER' SUCHMUSTER -dnh -- Trying to make bits uncopyable is like trying to make water not wet. The sooner people accept this, and build business models that take this into account, the sooner people will start making money again. -- Bruce Schneier
Hallo David, On Donnerstag 31 August 2006 18:20 wrote David Haller:
Am Mon, 28 Aug 2006, Wolfgang Golder schrieb:
Die Anzahl der Textzeilen zwischen den ###... ist immer verschieden. Es können mindestens 2 sein, aber auch 200. Mit grep kann ich jetzt wunderbar suchen und auch bestimmen welche Zeilen angezeigt werden. z.B. mit grep -5 'meinSuchtext' meinTestfile.txt jeweils 5 Zeilen vor und nach der Fundstelle anzeigen.
agrep -d 'TRENNMUSTER' SUCHMUSTER
super, genau das habe ich gesucht. Und die ganzen Optionen sind noch ein Sahnehäubchen obendrauf :-) Danke Wolfgang -- www.golder.de
participants (6)
-
Achim Schäfer
-
Bernd Obermayr
-
David Haller
-
Dr. Jürgen Vollmer
-
Joachim Tüns
-
Wolfgang Golder