sed Frage

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

sed Frage

Beitrag von fiberkill » 24.09.2014 08:07:58

Hallo zusammen,
ich hoffe Ihr könnt mir ein paar Tipps zu meinem Problem geben.
ich habe eine sehr große Textdatei , die ich nach einem bestimmten Inhalt durchsuchen muss.

Der zu suchende Inhalt sieht ungefähr so aus:

BEISPIELTEXT_DER_DATEI@0815 [XX YY20+AB]
744376 744160 660003 0 0 0 0 0

Die eckigen Klammern sind nur in diesen gesuchten Zeilen enthalten.
Was ich als Ausgabe brauche, ist der Inhalt der eckigen Klammern und die Zahl in der dritten Spalte der darauf folgenden Zeile.

Mein sed-Wissen ist nicht sehr groß aber ich hoffe Ihr könnt mir ein paar Tipps geben.

Vielen Dank im Voraus

fk

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

Re: sed Frage

Beitrag von uname » 24.09.2014 08:43:19

Das Problem ist, dass du in der Folgezeile noch wissen musst, dass es einen Treffer gab. Die sed-Lösung kenne ich leider nicht.

fgrep-Lösungsansatz:

Code: Alles auswählen

fgrep -A1 BEISPIEL datei
awk-Lösungsansatz:

Code: Alles auswählen

awk '{if ($0 ~ /BEISPIELTEXT/){gefunden=1;print $0} else {if (gefunden==1) {gefunden=0;print $3}}}' datei
Leider weiß ich nicht wie man den Inhalt der eckigen Klammern rausgeneriert.

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

Re: sed Frage

Beitrag von Meillo » 24.09.2014 09:17:47

fiberkill hat geschrieben: Der zu suchende Inhalt sieht ungefähr so aus:

BEISPIELTEXT_DER_DATEI@0815 [XX YY20+AB]
744376 744160 660003 0 0 0 0 0

Die eckigen Klammern sind nur in diesen gesuchten Zeilen enthalten.
Leider sagst du nicht nach was *genau* gesucht werden kann. Suche ich also Zeilen die ``BEISPIELTEXT_DER_DATEI'' enthalten, oder welche die irgendwo eckige Klammern haben, oder eine Zeile die genau so aussieht? Welches sind also die festen und welches die variablen Teile der gesuchten Zeile(n)?

Ich nehme einfach mal an, dass du diejenigen Zeilen suchst, die eckige Klammern enthalten.
Was ich als Ausgabe brauche, ist der Inhalt der eckigen Klammern und die Zahl in der dritten Spalte der darauf folgenden Zeile.

Mein sed-Wissen ist nicht sehr groß aber ich hoffe Ihr könnt mir ein paar Tipps geben.
Gibt es einen Grund, dass du eine Loesung in sed willst, oder vermutest du nur, dass sed ein geeignetes Tool waere? Das macht naemlich einen grossen Unterschied. Ich kann sowas mit sed schreiben, aber es waere umstaendlich im Vergleich zu einer Loesung mit awk. Ich waehle deshalb lieber awk.

Code: Alles auswählen

/\[.*\]/ {
	sub(/.*\[/,""); sub(/\].*/,"")
	klammern=$0
	getline
	printf("klammern: `%s' -- 3.feld: `%s'\n", klammern, $3)
}
Der Code ist ungetestet, er sollte so oder so aehnlich aber funktionieren.

Wenn's Fragen zum Verstaendis gibt, dann fragt!
Zuletzt geändert von Meillo am 24.09.2014 11:38:23, insgesamt 1-mal geändert.
Grund: Vertipper korrigiert: s/}/)/
Use ed once in a while!

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

Re: sed Frage

Beitrag von Meillo » 24.09.2014 09:31:21

uname hat geschrieben:Das Problem ist, dass du in der Folgezeile noch wissen musst, dass es einen Treffer gab. Die sed-Lösung kenne ich leider nicht.
`grep -A1' sieht in sed so aus:

Code: Alles auswählen

sed -n '/foo/{N;p}'
awk-Lösungsansatz:

Code: Alles auswählen

awk '{if ($0 ~ /BEISPIELTEXT/){gefunden=1;print $0} else {if (gefunden==1) {gefunden=0;print $3}}}' datei
Falls du in awk nicht nur im C-Stil programmieren willst, sondern im awk-Stil, dann versuch's mal in der Art:

Code: Alles auswählen

awk '
gefunden==1 {gefunden=0;print $3}
$0 ~ /BEISPIELTEXT/ {gefunden=1;print $0}
'
Eine awk-Anweisung besteht immer aus Bedingung und Aktion. Statt dass du die Bedinungen als if-Statement in den Aktionsteil einer Aktion steckst, die in jeder zeile ausgefuehrt wird, kannst du auch einfach Aktionen mit Bedingungen verwenden.

Und `$0 ~' kannst du weglassen, da das automatisch angenommen wird. Auch `print' verwendet ganz automatich $0, wenn man nichts angibt. Insofern waere dein Code in dieser Form awk-artiger:

Code: Alles auswählen

awk '
gefunden==1 {gefunden=0;print $3}
/BEISPIELTEXT/ {gefunden=1;print}
'
Use ed once in a while!

fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

Re: sed Frage

Beitrag von fiberkill » 24.09.2014 11:16:11

Hallo nochmal.
Vielen Dank an all, die mir geholfen haben.

Die AWK-Lösung von Meillo funktionierte einwandfrei.

Eine Frage hätte ich aber noch.
Das Ergebis dieses AWK-Befehls ist eine lange Liste.
Aus Gründer der Übersichlichkeit möchte ich jetzt noch, dass die Zahl der dritten Spalte der zweiten Zeile neben dem Inhalts der eckigen Klammern steht.

Beispiel:
So sieht der Abschnit in der Originaldatei aus:

BEISPIELTEXT_DER_DATEI@0815 [XX YY20+AB]
744376 744160 660003 0 0 0 0 0

Und so möchte ich ihn haben.
XX YY20+AB;660003

Gruss und Danke

FK

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

Re: sed Frage

Beitrag von uname » 24.09.2014 11:23:21

program.awk:

Code: Alles auswählen

/\[.*\]/ {
   sub(/.*\[/,""); sub(/\].*/,"")
   klammern=$0
   getline
   print klammern ";" $3;
}

Code: Alles auswählen

awk -f program.awk datei

fiberkill
Beiträge: 221
Registriert: 28.03.2007 09:08:30

Re: sed Frage

Beitrag von fiberkill » 24.09.2014 11:27:18

Man bist Du krass drauf.
das war genau das was ich wollte.

Vielen dank.

Wärst Du noch so nett und erklärst es mir. sonst muss ich beim nächsten Problem wieder posten.

fk

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

Re: sed Frage

Beitrag von uname » 24.09.2014 11:30:51

Ich verstehe recht wenig von awk. Aber das Programm von Meillo konnte ich entsprechend aufbereiten. Wobei nun nur noch nach eckigen Klammern gesucht wird. Solltest du was anderes suchen musst du es evtl. noch anpassen.
Dann statt

Code: Alles auswählen

/\[.*\]/ {
eher

Code: Alles auswählen

/BEISPIEL.*\[.*\]/ {

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

Re: sed Frage

Beitrag von Meillo » 24.09.2014 11:45:42

fiberkill hat geschrieben: Wärst Du noch so nett und erklärst es mir. sonst muss ich beim nächsten Problem wieder posten.
Klar.

Code: Alles auswählen

/\[.*\]/ {
Wendet den Aktionsblock (in geschweiten Klammern) nur auf Zeilen an, in denen irgendwas in eckigen Klammern steht.

Code: Alles auswählen

   sub(/.*\[/,""); sub(/\].*/,"")
Entfernt in diesen Zeilen alles bis zur oeffnenden und alles ab der schliessenden eckigen Klammer.

Code: Alles auswählen

   klammern=$0
Speichert das uebrig Gebliebene (= den Inhalt der eckigen Klammer) in der Variable `klammern'.

Code: Alles auswählen

   getline
Liest die naechste Zeile ein.

Code: Alles auswählen

   print klammern ";" $3;
Gibt den gespeicherten Inhalt von der eckigen Klammer, einen Strichpunkt und das dritte Feld der neu eingelesenen Zeile aus.
Macht dann mit der naechsten folgenden Zeile weiter ...
Use ed once in a while!

Antworten