sed multiline Text-Ersetzungfrage

Autor

Donnerstag, 21. Dezember 2006 12:16:48

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!

Enno Bartels

6 Antworten


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: 189 Punkte bei 15 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: 161 Punkte bei 17 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: 124 Punkte bei 16 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: 145 Punkte bei 15 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: 113 Punkte bei 2 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: 139 Punkte bei 3 Stimmen.
Den Beitrag bewerten: Gut / Schlecht

Ähnliche Artikel

Tipp der Woche

Schnell Multi-Boot-Medien mit MultiCD erstellen
Schnell Multi-Boot-Medien mit MultiCD erstellen
Tim Schürmann, 24.06.2014 12:40, 0 Kommentare

Wer mehrere nützliche Live-Systeme auf eine DVD brennen möchte, kommt mit den Startmedienerstellern der Distributionen nicht besonders weit: Diese ...

Aktuelle Fragen

Artikelsuche
Erwin Ruitenberg, 09.10.2014 07:51, 1 Antworten
Ich habe seit einige Jahre ein Dugisub LinuxUser. Dann weiß ich das irgendwann ein bestimmtes Art...
Windows 8 startet nur mit externer Festplatte
Anne La, 10.09.2014 17:25, 4 Antworten
Hallo Leute, also, ich bin auf folgendes Problem gestoßen: Ich habe Ubuntu 14.04 auf meiner...
Videoüberwachung mit Zoneminder
Heinz Becker, 10.08.2014 17:57, 0 Antworten
Hallo, ich habe den ZONEMINDER erfolgreich installiert. Das Bild erscheint jedoch nicht,...
internes Wlan und USB-Wlan-Srick
Gerhard Blobner, 04.08.2014 15:20, 2 Antworten
Hallo Linux-Forum: ich bin ein neuer Linux-User (ca. 25 Jahre Windows) und bin von WIN 8 auf Mint...
Server antwortet mit falschem Namen
oin notna, 21.07.2014 19:13, 1 Antworten
Hallo liebe Community, Ich habe mit Apache einen Server aufgesetzt. Soweit, so gut. Im Heimnet...

Jetzt auf den Mailinglisten

Re: [EasyLinux-Ubuntu] Dia-Show -Programm
Wolfgang Völker, 21.10.2014 15:20
Hallo Gerhard, Am 21.10.2014 14:22, schrieb Gerhard Blaschke: > Hallo Liste, > ich möchte gerne die...
[EasyLinux-Ubuntu] Dia-Show -Programm
Gerhard Blaschke, 21.10.2014 14:22
Hallo Liste, ich möchte gerne die Fotos einer Urlaubsreise am lokalen Rechner als Diashow ablaufen lassen....
Re: [EasyLinux-Ubuntu] zukünftiger_Standard-Desktop_bei_Debian?
Wilhelm Boltz, 21.10.2014 12:35
Hallo, Am Samstag, 18. Oktober 2014, 15:29:06 schrieb Thomas Lueck: > Am Samstag, den 18.10.2014, 12:42...
Re: [EasyLinux-Ubuntu] Updates bei *buntu
Thomas Lueck, 20.10.2014 18:32
Am Montag, den 20.10.2014, 18:11 +0200 schrieb Gerhard Blaschke: > Ich weiß nicht ob hinter Zentyal ei...
Re: [EasyLinux-Ubuntu] Updates bei *buntu
Gerhard Blaschke, 20.10.2014 18:11
Am 20.10.2014 um 17:30 schrieb Thomas Lueck: > Am Montag, den 20.10.2014, 07:33 +0200 schrieb Gerhard Blas...