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: 177 Punkte bei 19 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: 160 Punkte bei 20 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: 104 Punkte bei 31 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: 112 Punkte bei 31 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: 111 Punkte bei 5 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: 162 Punkte bei 6 Stimmen.
Den Beitrag bewerten: Gut / Schlecht

Ähnliche Artikel

Aktuelle Fragen

Wie kann man das berichtigen
Udo Muelle, 17.07.2016 20:39, 1 Antworten
Fehlschlag beim Holen von http://extra.linuxmint.com/dists/rosa/main/binary-i386/Packages Hash-S...
Installation Genimotion
Horst Müller, 15.07.2016 17:00, 1 Antworten
Hallo, ich kann Genimotion nicht installieren. Folgende Fehlermeldung habe ich beim Aufruf erh...
Probleme beim Hochfahren der Terastaion 5400 mit Unix-Distrib
Sheldon Cooper, 10.07.2016 09:32, 0 Antworten
Hallo ihr lieben, habe seit zwei Tagen das Problem, das das NAS (Raid5) nicht mehr sauber hoch...
Mit Firewire Videos improtieren?
Werner Hahn, 09.06.2016 11:06, 5 Antworten
Ich besitze den Camcorder Panasonic NV-GS330, bei dem die Videos in guter Qualität nur über den 4...
lidl internetstick für linux mint
rolf meyer, 04.06.2016 14:17, 3 Antworten
hallo zusammen ich benötige eure hilfe habe einen lidl-internetstick möchte ihn auf linux mint i...

Jetzt auf den Mailinglisten

Re: [EasyLinux-Ubuntu] KMail und MDA
Steffen Weyh, 23.07.2016 16:00
Selbst wenn es technisch möglich wäre, die Konfiguration von 15 einzelnen SMTP-Ausgängen wäre in meinen Augen e...
Re: [EasyLinux-Ubuntu] KMail und MDA
heiko, 23.07.2016 15:39
Am Samstag, 23. Juli 2016, 14:50:31 schrieb Richard Kraut: > Am Samstag, den 23.07.2016, 11:09 +0200 schri...
Re: [EasyLinux-Ubuntu] KMail und MDA
Richard Kraut, 23.07.2016 14:50
Am Samstag, den 23.07.2016, 11:09 +0200 schrieb heiko: Das hört sich nach unserem alten Heinz-Stefan an. :-)...
Re: [EasyLinux-Ubuntu] KMail und MDA
heiko, 23.07.2016 13:57
Am Samstag, 23. Juli 2016, 12:11:32 schrieb Steffen Weyh: > Nicht gut! > Welche anderen Möglichkeiten...
Re: [EasyLinux-Ubuntu] KMail und MDA
Wilhelm Boltz, 23.07.2016 13:09
Am Samstag, 23. Juli 2016, 11:09:13 CEST schrieb heiko: > [...] > Greift nicht. Und die neuen Konfigu...