Frage zu awk/sed

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Frage zu awk/sed

Beitrag von Duff » 04.03.2009 16:32:13

Hallo,

ich habe mal wieder eine Frage zu sed/awk (Meillo) ;-)

Und zwar mache auf eine Datei folgendes:

Code: Alles auswählen

awk 'ORS=/<\/irgendeintag>/ ? "\n\n" : " "' tmp|sed -ne '1p'
Gibt mir die erste Zeile aus.

Mache ich das gleiche mit $p anstelle von 1p, so bekomme ich nicht, wie erhofft die letzte Zeile ausgegeben, sondern nichts.

Wieso?
Oh, yeah!

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

Re: Frage zu awk/sed

Beitrag von Meillo » 04.03.2009 20:31:35

Hallo, da bin ich ;-)

Ich vermute, ohne AWK ist es alles klar.

Mit AWK ist auch alles klar, wenn man weiß weshalb. ;-) Denn du bekommst schon die letzte Zeile ausgegeben ... nur ist das nicht das was du willst.

Das AWK-Script hängt an jede Zeile mit dem Tag, bei der Ausgabe zwei Newline ('\n') an (anstatt eines per default). Zeilen ohne das Tag bekommen gar kein Newline angehängt, sondern nur ein Leerzeichen. Somit wird effektiv die nächste Zeile hinten angehängt.

Wenn nun deine letzte Zeile das Tag enthält, werden ihr am Ende zwei Newline-Zeichen angehängt. D.h. die Ausgabe des AWK-Scripts endet in diesem Fall mit:

Code: Alles auswählen

[...]
foo </irgendeintag> bar\n
\n
Wenn du dann mit sed die letzte Zeile willst, bekommst du sie auch, aber du willst eigentlich die vorletzte Zeile.


Die einfachste Lösung wäre wohl nicht zwei sondern nur ein Newline-Zeichen zu verwenden. Aber das kommt auf die genaue Problemstellung an.

btw: Whitespace ist auch existent ... man sieht ihn halt so schlecht. ;-)
Tipp: Die Ausgabe durch `od -c' zu pipen ist in solchen Fällen oft sehr hilfreich.
Use ed once in a while!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Re: Frage zu awk/sed

Beitrag von Duff » 05.03.2009 09:35:09

Danke dir mal wieder Meillo.

Ich hatte es mit awk und NR probiert, wobei ich die letzte Zeile mit ENDE=$(awk ' END { print NR }') ermittelt habe und wollte diese Variable in ...|awk 'NR==$ENDE' einbringen, was aber nicht zum Erfolg geführt hat.

Ich habe mich für die einfachere Variante mit ...|head -1 und ...|tail -1 entschieden. So funktioniert es.

Leider kann ich bei meinem awk ORS diesen Befehl nicht so aufrufen, dass er keine Leerzeilen macht, also quasi so:

Code: Alles auswählen

wk 'ORS=/<\/irgendeintag>/ ? "\n\n" : ""' tmp
Oh, yeah!

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

Re: Frage zu awk/sed

Beitrag von Meillo » 05.03.2009 13:06:17

Duff hat geschrieben:Leider kann ich bei meinem awk ORS diesen Befehl nicht so aufrufen, dass er keine Leerzeilen macht, also quasi so:

Code: Alles auswählen

wk 'ORS=/<\/irgendeintag>/ ? "\n\n" : ""' tmp
Nein, so:

Code: Alles auswählen

awk 'ORS=/<\/irgendeintag>/ ? "\n" : " "' tmp
Use ed once in a while!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Re: Frage zu awk/sed

Beitrag von Duff » 05.03.2009 13:23:55

Sorry, hatte mich vertan.

Ich meinte folgendes:

Code: Alles auswählen

awk 'ORS=/^$/ ? "\n\n" : " "'
würde ich gerne so abändern, dass anschließend keine Leerzeichen mehr zwischen den einzelnen Zeichen vorhanden sind (quasi habe ich dann bei mir nur noch eine Zeile).

Funktioniert nicht:

Code: Alles auswählen

awk 'ORS=/^$/ ? "\n\n" : ""'
Oh, yeah!

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

Re: Frage zu awk/sed

Beitrag von Meillo » 05.03.2009 15:02:15

Ich habe es mit ?: auch nicht hingekriegt, liegt vielleicht daran, dass der leere String als Nichts betrachtet wird ??

So jedenfalls funktionierts:

Code: Alles auswählen

awk '{ORS=""} /foo/{ORS="\n\n"} {print}'
Zuerst für jede Zeile ORS auf den leeren String setzen.
Für Zeilen in denen ``foo'' vorkommt wird ORS aber geändert.
Anschließend jede Zeile ausgeben.


Ich hoffe das ist das was du wolltet ... bin mir nämlich nicht sicher.
Use ed once in a while!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Re: Frage zu awk/sed

Beitrag von Duff » 05.03.2009 15:29:43

Unser awk-Meister :wink:

Aber was kann ich gegen die Meldung machen, dass die awk-Zeile zu lang ist. Mehr als 3.000 Bytes?
Musste bzw. habe diese Zeile dann mit dem perl-Einzeiler im Skript bearbeitet. Aber gibt es dann mit awk wirklich keine Möglichkeit?

Danke & Gruß,
Daniel
Oh, yeah!

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

Re: Frage zu awk/sed

Beitrag von Meillo » 05.03.2009 16:24:48

Duff hat geschrieben:Aber was kann ich gegen die Meldung machen, dass die awk-Zeile zu lang ist. Mehr als 3.000 Bytes?
Musste bzw. habe diese Zeile dann mit dem perl-Einzeiler im Skript bearbeitet. Aber gibt es dann mit awk wirklich keine Möglichkeit?
Ich vermute, dass die Länge des Zeilenpuffers (array of char) bei der von dir verwendeten Implementierung halt fix ist.
Da kannst du entweder diese Länge im awk-Quellcode vergrößern und neu kompilieren, oder gawk verwenden, das AFAIK dynamisch Speicher reserviert.

... oder du änderst dein Script, damit keine Monsterzeilen erzeugt werden. Du könntest mal folgenden Code testen:

Code: Alles auswählen

awk '{ if (/bash/) {printf("%s\n\n", $0) } else {printf ("%s", $0) } }'
(Falls das Problem bestehen bleibt, poste die genaue Fehlermeldung und möglichst irgendwelche Testdaten.)
Use ed once in a while!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Re: Frage zu awk/sed

Beitrag von Duff » 05.03.2009 16:32:58

Danke, aber es handelt sich hier um sed unter HP-UX und da darf ich nichts am Quellcode ändern. Außerdem haben wir keine gnu-Varianten installiert.
Oh, yeah!

Antworten