sed multiline Text-Ersetzungfrage

Enno Bartels - Donnerstag, 21. Dezember 2006 12:16:48 - 6 Antworten

Hallo Ich versuche einen großen Text mittels SED One-Liner'n in ein anderes Aussehen zu konvertieren.
Jedoch funktioniert das bei Ausdrücken mit mehreren Zeilen nicht wie gewünscht!

Ich habe schon eine ganze Menge Howtos, One-lines etc. im Internet gelesen.
Aber die richtige Antwort bzw den richtigen Ansatz habe ich noch nicht gefunden.

Es handelt sich um ein Mehrzeilen-Problem, was in meinem Testtext an der 3. Frage von "E" bzw. "eee" zu erkennen ist. Ich bin für jede Hilfe bzw. jeden Tipp dankbar!

Input Text:
E: Gab es bla bla bla schon lange ?

kkk: Nein nein nein. Da war das ein dicker Hund!

E: Ein Hund - mit Fell ?!

kkk: Ja ja.
     Ein dicker Hund mit hellem Fell.

E: Was hat der gemacht?
     Hatte der braune Augen ?
     Oder was ?

kkk: Weiss ich nicht!



<strong>Mein noch nicht ganz perfekter SED onliner:</strong>
 more test_text.txt | sed 's/E: \(.*\)$/eee: <strong>/'   
 


<strong>Das nicht ganz perfekte Ergebnis:</strong>
eee: <strong>Gab es bla bla bla schon lange ?</strong>

kkk: Nein nein nein. Da war das ein dicker Hund!

eee: <strong>Ein Hund - mit Fell ?!</strong>

kkk: Ja ja.
     Ein dicker Hund mit hellem Fell.

eee: <strong>Was hat der gemacht?</strong>
     Hatte der braune Augen ?
     Oder was ?

kkk: Weiss ich nicht!



<strong> Das gewünschtes Ergebnis:</strong>
eee: <strong>Gab es bla bla bla schon lange ?</strong>

kkk: Nein nein nein. Da war das ein dicker Hund!

eee: <strong>Ein Hund - mit Fell ?!</strong>

kkk: Ja ja.
     Ein dicker Hund mit hellem Fell.

eee: <strong>Was hat der gemacht?
     Hatte der braune Augen ?
     Oder was ?<strong></strong></strong>

kkk: Weiss ich nicht!

Antworten
Re: sed multiline Text-Ersetzungfrage
Dieter Drewanz, Sonntag, 15. Juli 2007 19:20:10
Ein/Ausklappen

Anbei bin ich per Zufall auf eine mögliche Lösung der Aufgabe gestoßen. Eine Abhängigkeit geht mit dem "N" Kommando (dieses Kommando erweitert die Möglichkeiten um eine Abhängigkeit über eine Zeile hinaus zu bekommen). Unten habe ich die Quelle als Link angegeben, und falls diese nicht mehr exestiert, die betreffenden Stellen hier hinein kopiert.

The N command no longer discards the contents of the pattern space upon reaching the end of file. This is not a bug, it's a feature. However, it breaks certain scripts which relied on the older behavior of N. 'N' adds the Next line to the pattern space, enabling multiple lines to be stored and acted upon. Upon reaching the last line of the file, if the N command was issued again, the contents of the pattern space would be silently deleted and the script would abort (this has been the traditional behavior). For this reason, sed users generally wrote: $!N; # to add the Next line to every line but the last one. However, certain sed scripts relied on this behavior, such as the script to delete trailing blank lines at the end of a file (see script #12 in section 3.2, "Common one-line sed scripts", above). Also, classic textbooks such as Dale Dougherty and Arnold Robbins' sed & awk documented the older behavior. The GNU sed maintainer felt that despite the portability problems this would cause, changing the N command to print (rather than delete) the pattern space was more consistent with one's intuitions about how a command to "append the Next line" ought to behave. Another fact favoring the change was that "{N;command;}" will delete the last line if the file has an odd number of lines, but print the last line if the file has an even number of lines. To convert scripts which used the former behavior of N (deleting the pattern space upon reaching the EOF) to scripts compatible with all versions of sed, change a lone "N;" to "$d;N;". # GNU style sed script $!N; # except for last line, get next line s/^\([0-9]\{5\}\).*\n\1.*//; # if first 5 digits of each line # match, delete BOTH lines. t skip P; # print 1st line only if no match :skip D; # delete 1st line of pattern space and loop #---end of script---

[1] http://www.student.northpark.edu/pemente/sed/sedfaq6.html



Bewertung: 191 Punkte bei 24 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
Re: sed multiline Text-Ersetzungfrage
Dieter Drewanz, Donnerstag, 21. Dezember 2006 21:15:39
Ein/Ausklappen

Ganz kompliziert könnte man es mit Chromsky Hierarchie des Parsings erklären, warum das Problem nicht so in einem Schritt geht. Das "bold" Fettdruck wird durch die Codezeichenkette "eee:" gesetzt. Diese ist nur in der ersten Zeile, also logisch erfolgt text und in dem folgenden Zeilen logischerweise nicht. Es ginge nur wenn man in Abhängigkeit von der Vorzeile eine Merkeer setzen würde, wenn "eee:" gefunden, mache immer boldfett, bis eine Lerrzeile kommt (oder das ersten Zeichen "kein Space und : und nicht eee:"). Daher geht es entweder nur z.B. mit einem fallabhängigen perl Skript oder über eine zwei/drei Schritte Umsetzung.
Entferne in nicht leeren Zeilen den Zeilenumbruch und ersetze diesen durch
in output1.txt
Dann lasse Deine Ersetzung laufen in output2.txt.
Nun suche nach den
und mache daraus wieder Zeilenumbrüche in output3.txt, das nun das Ergebnis enthält.



Bewertung: 178 Punkte bei 25 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: sed multiline Text-Ersetzungfrage
Enno Bartels, Freitag, 22. Dezember 2006 13:11:35
Ein/Ausklappen

Schön und gut, aber es müßte doch auch so mit SEDs fast unbegrenzten Fähigkeiten einer Turing-Maschine möglich sein dies direkt zu lösen.

Besonders interessant ist hierbei der "N;" Operator. Mit ihm lassen sich mehrere Zeilen zu einer zusammenfügen.

Bisher brachten meine Versuchsreihen hier jedoch nicht den gewünschten Erfolg!

more test_text.txt | sed 'N; s/E: \(.*\)\n\n/eee: \1/'

Weitere Ideen und Verbesserungsvorschläge ?




Bewertung: 110 Punkte bei 43 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: sed multiline Text-Ersetzungfrage
Ugglan , Freitag, 05. Januar 2007 05:36:26
Ein/Ausklappen

Hallo,

ich hatte mal etwas ähnliches, wo ich Text zeilenübergreifend mit sed ersetzen wollte. Das war mein Einstieg in Perl :-)

Das Problem ist, daß sed zeilenbasierend arbeitet. Du brauchst aber ein Suchmuster, das Zeilenumbrüche weitgehend ignoriert und stattdessen auf Kombinationen von Zeilenbeginn/-ende, Buchstabenkombinationen und Leerzeilen reagiert, ohne diese aber zu entfernen. Das geht mit sed nicht, da es Zeilenumbrüche zwar lesen, aber nicht ausgeben kann.

Lösungsvorschlag 1: Nimm Perl. (Die Ersetzungsfunktion in Perl hat fast dieselbe Syntax wie sed.) Oder Python oder eine andere (Skript)sprache, die reguläre Ausdrücke verarbeiten kann.

Lösungsvorschlag 2: Ersetze in einem ersten Durchlauf alle Zeilenumbrüche durch Hilfszeichen. Dann führst Du Deine Ersetzung durch, und ersetzt schließlich Deine Hilfszeichen wieder durch Zeilenumbrüche. Was leider dadurch erschwert wird, daß sed mindestens einen Zeilenumbruch am Ende Deiner Monsterzeile benötigt und -- wie gesagt -- leider keine Zeilenumbrüche schreiben kann...

Dummerweise liegen zwischen mir und meinen perl-Referenzen gerade ca. 1000 km Wasser, so daß ich Dir keine getestete Version anbieten kann.

Das Ganze sollte etwa so aussehen:

#!/usr/bin/perl -w (oder #!/bin/perl -w)

open(INFILE, "input.txt") or die "Can't open input.txt: $!";
open(OUTFILE, ">output.txt") or die "Can't open output.txt: $!";

my @text = ;

@text =~ s/E: (.*?)\n\n/eee: $1\n\n/gs;

print OUTFILE @text;
close INFILE;
close OUTFILE;

Zur Syntax:
"s/irgendwas/anderes/" ist das Pendant zu "sed s/irgendwas/anderes/", bezogen auf die Variable @text. Der Buchstabe g sorgt dafür, daß alle (statt nur das erste) Vorkommen ersetzt werden, s sorgt dafür, daß der Joker "." auch Zeilenumbrüche umfaßt. Der Multiplikator *? frißt im Gegensatz zu seinem "gierigen" Bruder * nur die minimale Anzahl Zeichen, die nötig ist, um das Muster zu erfüllen (mit * hättest Du sonst ein beim ersten und ein beim letzten Eintrag Deiner Datei).

Eine Übersicht der Befehle findest Du unter [1] und [2], während [3] ausführlichst auf Suchmuster eingeht.

Ich hoffe, ich habe Dich jetzt nicht verschreckt :-)

Viel Erfolg,

Ugglan

[1] http://perldoc.perl.org/perlintro.html#Files-and-I%2fO
[2] http://perldoc.perl.org/perlintro.html#Regular-expressions
[3] http://perldoc.perl.org/per...ml#Regexp-Quote-Like-Operators



Bewertung: 109 Punkte bei 42 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
sed mit 2 zeilen
the peacemaker (unangemeldet), Dienstag, 09. Februar 2010 17:10:54
Ein/Ausklappen

bei der Suche nach einer Lösung habe ich im Internet diesen Artikel über SED gelesen. Kann mir vielleicht jemand bei der Lösung helfen? Der Skript muss in die 16. Zeile die Daten aus der 17. Zeile einfügen und etwas hinzufügen:

input:

<title>mein text</title>
<link>mein link</link>

output:

<title><a href="mein link">mein text</a></title>
<link>mein link</link>

ich habe an das Kommando

# Füge Zeilenpaare nebeneinander zusammen (entspricht "paste")
sed '$!N;s/\n/ /'

gedacht, kam damit aber nicht weiter. Als Hobby-Programmierer wäre ich Euch für die Hilfe sehr dankbar!



Bewertung: 139 Punkte bei 11 Stimmen.
Den Beitrag bewerten: Gut / Schlecht
-
Re: sed mit 2 zeilen
DieterD (unangemeldet), Dienstag, 09. Februar 2010 21:30:45
Ein/Ausklappen

folgendes auf der bash:

IFS=$'\n'; for i in $(echo -e "dummy dummy vorher""\n""<title>mein text</title>""\n""<link>mein link</link>""\n""dummy dummy nachher") ; do a0=$aa ; aa=$(echo $i | grep "<title>" | grep "</title>" | sed -e 's/<title>//' -e 's/<\/title>//' ) ; bb=$(echo $i | grep "<link>" | grep "</link>" ); cc=$(echo $bb | sed -e 's/<link>//' -e 's/<\/link>//' ) ; if [[ "$a0" != "" && "$cc" != "" ]] ; then echo -e "<title><a href="\"$a0\"">$cc</a></title> \n<link>$cc</link>" ; fi ; if [[ "$aa" == "" && "$cc" == "" ]] ; then echo $i ; fi ; done

ergibt:

dummy dummy vorher
<title><a href="mein text">mein link</a></title>
<link>mein link</link>
dummy dummy nachher




Bewertung: 158 Punkte bei 11 Stimmen.
Den Beitrag bewerten: Gut / Schlecht

Ähnliche Artikel

Aktuelle Fragen

WLAN lässt sich nicht einrichten
Werner Hahn, 21.03.2017 14:16, 0 Antworten
Dell Latitude E6510, Ubuntu 16.4, Kabelbox von Telecolumbus. Nach Anklicken des Doppelpfeiles (o...
"Mit Gwenview importieren" funktioniert seit openSuse 42.2 nicht mehr
Wimpy *, 20.03.2017 13:34, 2 Antworten
Bisher konnte ich von Digitalkamera oder SD-Karte oder USB-Stick Fotos mit Gwenview importieren....
Ich habe eine awk Aufgabe und bekomme es nicht so Recht hin
Dennis Hamacher, 10.03.2017 18:27, 1 Antworten
Ich hoffe Ihr könnt mir dabei helfen oder mir zeigen wie der Befehl richtig geschrieben wird. Ich...
Unter Linux Open Suse Leap 42.1 einen Windows Boot/ ISO USB Stick erstellen...
Tim Koetsier, 07.03.2017 15:26, 1 Antworten
Hallo, weiß jemand wie ich oben genanntes Vorhaben in die Tat umsetzen kann ? Wäre echt dankba...
Druckertreiber installieren OpenSuse42.1
Tim Koetsier, 07.03.2017 15:22, 1 Antworten
hallo, kann mir BITTE jemand helfen ich verzweifel so langsam. Habe einen Super Toner von Canon...

Jetzt auf den Mailinglisten

Re: [EasyLinux-Ubuntu] Videoplayer_für_Ubuntu
Heiko, 28.03.2017 20:23
Am Dienstag, 28. März 2017, 19:22:00 CEST schrieb Willi Zelinka: Hallo Uwe,hallo Willi > > vl...
Re: [EasyLinux-Ubuntu] Videoplayer_für_Ubuntu
Willi Zelinka, 28.03.2017 19:22
Hallo Uwe, Am Dienstag, 28. März 2017, 10:17:29 CEST schrieb Uwe Herrmuth: > Hallo Willi, > >...
Re: [EasyLinux-Ubuntu] Downloads von Windowsprogrammen unter Linux
Karl-Heinz, 28.03.2017 17:55
Am Tue, 28 Mar 2017 09:19:49 +0200 schrieb Uwe Herrmuth : Hallo Uwe, :-))))) > Für FF gibt es ein Ad...
Re: [EasyLinux-Ubuntu] Videoplayer_für_Ubuntu
Uwe Herrmuth, 28.03.2017 10:17
Hallo Willi, Willi schrieb am 21.03.2017 um 15:08: > mit dem als Standard installiertem Totem gibt es nu...
Re: [EasyLinux-Ubuntu] Dateimanager Linux Mint18 Cinnamon
Uwe Herrmuth, 28.03.2017 10:00
Hallo Tanja, Tanja schrieb am 27.03.2017 um 19:04: > könnt Ihr mir einen Dateimanager in 2-Fenstertechni...