Textmanipulation auf der Shell

Hallo,

kennt jemand von euch einen schlanken und eleganten Weg aus einer Datei mit dem Inhalt

...
...
foo bar Establ
 inet.0: 30/23476/0
boo far Establ
 inet.0: 207/336/0
...
...

so etwas

...
...
foo bar Establ inet.0: 30/23476/0
boo far Establ inet.0: 207/336/0
...
...

zu machen? sed kann keine newlines, weil es die gar nicht sieht, tr kann keine Zeichenfolgen, weil es dafür nicht gemacht ist, awk interessiert sich mehr für Spalten als für Zeilen und ist mir - wie wohl vielen - kaum über „print $1“ hinaus bekannt.

perl oder php stehen nicht zur Verfügung.

Gruß,

Malte

PS: Es ist _nicht_ deterministisch _jede_ zweite Zeile, der Rest der Datei kann also „irgendwie“ aussehen und soll bewahrt werden.

Hallo,

sed kann keine newlines, weil es die gar nicht
sieht, tr kann keine Zeichenfolgen, weil es dafür nicht
gemacht ist, awk interessiert sich mehr für Spalten als für
Zeilen und ist mir - wie wohl vielen - kaum über „print $1“
hinaus bekannt.

Wie wäre es mit einer Kombination aus „tr“ und „sed“? Erst mit „tr“ die newlines rauskicken, dann mit dem sed durchforsten und an passenden Stellen wieder newlines einfügen.

Vermutlich geht das sogar mit einem Einzeiler (und ein paar pipes).

Gruß

Fritze

Hallo,

sed kann keine newlines, weil es die gar nicht
sieht, tr kann keine Zeichenfolgen, weil es dafür nicht
gemacht ist, awk interessiert sich mehr für Spalten als für
Zeilen und ist mir - wie wohl vielen - kaum über „print $1“
hinaus bekannt.

Wie wäre es mit einer Kombination aus „tr“ und „sed“? Erst mit
„tr“ die newlines rauskicken, dann mit dem sed durchforsten
und an passenden Stellen wieder newlines einfügen.

Kranker Vorschlag, genau sowas such ich :wink: Wird ein bisschen knifflig, diese passenden Stellen zu identifizieren, sollte aber machbar sein.

Ich spiel mal weiter damit herum.

Gruß,

Malte

> ...  
> ...  
> foo bar Establ  
> inet.0: 30/23476/0  
> boo far Establ  
> inet.0: 207/336/0  
> ...  
> ...

so etwas

> ...  
> ...  
> foo bar Establ inet.0: 30/23476/0  
> boo far Establ inet.0: 207/336/0  
> ...  
> ...

zu machen? sed kann keine newlines, weil es die gar nicht
sieht, tr kann keine Zeichenfolgen, weil es dafür nicht
gemacht ist, awk interessiert sich mehr für Spalten als für
Zeilen und ist mir - wie wohl vielen - kaum über „print $1“
hinaus bekannt.

Als Iterationsanfang wuerd ich’s mal durch

awk '/^[^]/{printf("\n%s ",$0);} /^[]+/{printf("%s ", $0);} END{printf("\n");}'

pipen. Das hat den Nachteil, einen haesslichen ueberfluessigen Zeilenumbruch am Anfang zu haben, den man „Nachbessern“ muesste, und eine riesig fette libm in den Speicher zu wuchten, ganz zu schweigen vom awk selber, aber den Vorteil, dass es zugegebenermassen in gewissen Grenzen lesbarer als

sed -n '1h;2,$H;${x;s%\n %%g;p}'

ist.

HTH,
Gruss vom Frank.

sed -n ‚1h;2,$H;${x;s%\n%%g;p}‘

Okay, tut, was es soll. Wenn Du mir nun noch verständlich aufdröselst, WARUM zur Hölle es das tut, dann schuldest Du mir keine Kiste Bier mehr. Oder ich Dir im Gegenzug eine, wie Du willst.

Gruß,

Malte

Die Zitatfunktion von w-w-w wird auch immer kaputter: das zitierte sed-Zeugs war in Deinem Beitrag gar nicht zu lesen.

> sed -n '1h;2,$H;${x;s%\n%%g;p}'

Okay, tut, was es soll. Wenn Du mir nun noch verständlich
aufdröselst, WARUM zur Hölle es das tut,

Ein Kollege wuerde sage, dass das doch total trivial, selbsterklaerend und normiert ist… :wink:

Okay, dass auch sed wie jede halbwegs anstaendige Programmiersprache (ausser python) ein ; zur Trennung von einzelnen Befehlen verwendet, ist vielleicht bekannt. Vielleicht auch noch, dass { } zur Gruppierung von Befehlen verwendet werden. Und das jeder einzelne Befehlsgruppe wie [ADDR]ZEUGS aufgebaut ist und das optionale ADDR evtl. auch mal ADDR1,ADDR2 sein kann und ZEUGS immer, was getan werden soll, wenn ADDR auf die derzeitige Zeile passt. Dann muss man eigentlich nur noch wissen, was die kryptischen Buchstaben bedeuten (info sed) und dass sed den Eingabestrom zeilenweise vom abschliessenden newline befreit (das ist der Grund, warum ein einfaches s/\n// nie funktionieren wird) in den pattern space laedt. Dann kriegt man

1h

-> wenn Du in der ersten Zeile bist ueberschreibe den hold space mit dem Inhalt des pattern space,

2,$H

-> wenn Du irgendwo zwischen der 2. und letzten Zeile (inklusive) bist fuege ein newline und dann den Inhalt des pattern space an den hold space an (das hat den charmanten Vorteil, nicht zu matchen, wenn der input stream nur eine Zeile hat und so keine ueberfluessigen Zeilenumbrueche hinzuzufuegen),

${ }

-> wenn Du in der letzten Zeile bist fuehre diese Gruppe aus,

x

-> tausche den Inhalt von hold space und pattern space (s/// kann nur auf dem pattern space arbeiten),

s/\n //g

-> ersetze ein newline gefolgt von einem Leerzeichen durch nichts und das global (also im gesamten pattern space); die Verwendung der % statt der uebichen / dienen nur der Obfuskierung ;-p (hey, ich habe zuerst ueberlegt, $ statt / zu verwenden),

p

-> schreibe den Inhalt des pattern space raus.

dann schuldest Du mir keine Kiste Bier mehr.

Boah, so’n Scheiss merkt der sich…

Oder ich Dir im Gegenzug eine, wie Du willst.

Ich trink doch gar kein Bier.

Gruss vom Frank.

1 Like