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: 209 Punkte bei 30 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: 199 Punkte bei 31 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: 120 Punkte bei 47 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: 119 Punkte bei 46 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: 158 Punkte bei 14 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: 174 Punkte bei 14 Stimmen.
Den Beitrag bewerten: Gut / Schlecht

Ähnliche Artikel

Aktuelle Fragen

Bash awk Verständnis-Frage
Josef Federl, 22.07.2017 17:46, 2 Antworten
#!/bin/bash # Skriptdateiname = test.sh spaltennummer=10 wert=zehner awk '{ $'$spaltennummer'...
Bash - verschachtelte Variablenersetzung, das geht doch eleganter als meine Lösung?
Josef Federl, 18.07.2017 20:24, 2 Antworten
#!/bin/bash #Ziel des Skriptes wird sein die ID zu extrahieren hier nur als Consolentest: root@...
Speicherplatzfreigabe mit "sudo apt-get clean" scheitert
Siegfried Böttcher, 16.07.2017 21:16, 2 Antworten
Speicherplatzfreigabe mit "sudo apt-get clean" scheitert, weil aus mir unerfindlichen Gründen im...
Möchte Zattoo vom PC am Fernsehgerät sehen können
Ilona Nikoui, 15.07.2017 18:25, 3 Antworten
Hallo, ich habe mein Fernsehgerät, ein LG 26LE3300 mit dem PC verbunden per HDMI Kabel, wie empfo...
TUXEDO und Hardwareauswahl , fragwürdig / Kritik
Josef Federl, 11.07.2017 12:44, 7 Antworten
Auf tuxedocomputers.com steht: "....Aber wir können auch Linux und das so, dass "einfach" alles...

Jetzt auf den Mailinglisten

Re: [EasyLinux-Ubuntu] GDM3 nach Dist-Upgrade Debian 8 Jessie auf Debian 9 Stretch
Richard Kraut, 25.07.2017 20:04
Am Freitag, den 21.07.2017, 10:49 +0200 schrieb Karl-Heinz: > Der zweite: GDM 3 verträgt sich wohl nicht m...
Re: [EasyLinux-Ubuntu] Technische Frage: 4G/LTE Router
Udo Teichmann, 25.07.2017 19:18
Am Dienstag, den 25.07.2017, 09:59 +0200 schrieb Heiko Ißleib: Hallo Heiko > Ich habe das längerfristig...
Re: [EasyLinux-Ubuntu] Technische Frage: 4G/LTE Router
Heiko, 25.07.2017 09:59
Am Montag, 24. Juli 2017, 15:25:36 CEST schrieb Udo Teichmann: Hallo Udo. > > Internet war bei mir...
Re: [EasyLinux-Ubuntu] Debian Stretch Suspend to Disk (Ruhezustand)
Richard Kraut, 24.07.2017 20:58
Am Mittwoch, den 05.07.2017, 22:25 +0200 schrieb Horst: > Hmm, da muss wohl was schiefgelaufen sein beim U...
[EasyLinux-Ubuntu] Technische Frage: 4G/LTE Router
Udo Teichmann, 24.07.2017 15:25
Hallo Liste Internet war bei mir bisher eher ein Trauerspiel. Stationär Altvertrag von Freenet, schon immer...