PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ganze Absätze ersetzen



ulukai
08.05.2006, 20:23
Hallo Leute
Ich bin gerade dabei an folgendem Problem zu verzweifeln, ich hoffe Ihr könnt mir helfen.
Ich habe recht Viele Textdateien in denen ich ganze Absätze suchen und ersetzen muß. Außerdem muß ich Teile des alten Absatzes in den neuen einbauen.
Also zum Beispiel:

Text
Text
A
A
A ->"Name"
A

soll zu

Text
Text
B ->"Name"
B

werden. "Name" steht dabei immer für etwas anderes. Das Suchpattern soll also:

A
A
A -> *
A

oder so sein. Mit sed bin ich nicht weitergekommen und ein Bekannter meint mit Perl sollte es gehen...
Besten Dank für eure Hilfe

Xanti
08.05.2006, 20:37
Yep, Perl ist dafür geeignet. Dein Beispiel lässt sich mit



perl -pi -e 's/Text\nText\nA\nA\nA ->"Name"\nA/Text\nText\nB ->"Name"\nB/g' file


erschlagen. Dabei sorgt "-0\777" dafür, dass Perl das File als ein String einliest. Deswegen darf das File nicht zu gross sein (ein paar MB). "\n" entspricht dem Newline an jedem Zeilenende.

Gruss, Xanti

ulukai
08.05.2006, 20:57
Danke für die schnelle Antwort! So ganz habe ich es nocht nicht verstanden.

Mit "Name" meine ich eigentlich das in den jweiligen Textdateien dafür immer etwas anderes steht was in den neuen Absatz übernommen werden soll. Kann ich bei Perl mit den "normalen" bash regular expressions arbeiten? Also so etwas wie

perl -pi -e 's/Text\nText\nA\nA\nA ->"(.*)"\nA/Text\nText\nB ->"\1"\nB/g' file

Muß ich bei Perl Sonderzeichen auch mit einem \ versehen (etwas \[ für [)?

Xanti
08.05.2006, 21:07
Im Grunde schon, obwohl die Bash-Regexps eher von Perl abstammen. Dein Beispiel ist syntaktisch richtig. Falls Name über mehrere Zeilen geht, solltest Du die Option /s zusätzlich (also /gs statt /g) wählen, damit "." auch "\n" matcht. Folgende Sonderzeichen haben eine Sonderfunktion beim Matchen und müssen deswegen "escaped" werden: +?.*^$()[{|\

Gruss, Xanti

ulukai
08.05.2006, 21:11
Besten Dank! Ich werds gleich morgen in der Uni testen.

Wolfgang
08.05.2006, 21:22
Hallo
Geht auch mit sed :D



wolle@Nietzsche:~/temp
$ cat testfile
text
mehr text mit umbruch

A
A
A->Namea
A
mehr text
noch mehr text
A
A->Namea
text
text

wolle@Nietzsche:~/temp
$ sed -ne '/^A\|A->.*$/!p;/^A\|A->.*$/{s/\(A->.*\)$/B->NameB/g;s/A/B/;p}' testfile
text
mehr text mit umbruch

B
B
B->NameB
B
mehr text
noch mehr text
B
B->NameB
text
text
wolle@Nietzsche:~/temp
sed --version
GNU sed Version 4.1.4
Copyright (C) 2003 Free Software Foundation, Inc.




Wenn du GNU sed hast, kennt auch sed die Option -i um die datei direkt zu editieren.
Mit perl ist die Lösung aber für kleine Dateien besser, da du dort auch ein Backup angeben kannst.
Bei großen Dateien geht es auch mit sed.
Hast du kein GNU sed , bau dir eine einfache Schleife drum und arbeite mit Umleitung.


for I in $(find -iname "name*"); do sed -ne '...' $I > $I_output&& cat $I_output >$I; done

oder mit while read oder oder...;)
HTH
Gruß Wolfgang

Edit// Sed noch etwas verbessert,damit Namea nicht feststeht und nur A am Anfang verändert wird, nicht aber in der Zeilenmitte.

ulukai
09.05.2006, 10:26
Hallo, muss nochmal nerven...

hollstei@george:~> cat ptest
Text
Name
Neu
hollstei@george:~> perl -pi -e 's/Text\nName/Tux\nTux/g' ptest
hollstei@george:~> cat ptest
Text
Name
Neu
hollstei@george:~>

Wieso funktioniert das nicht? Ich wollte ersteinmal ein einfachen Test machen...
Beste Gruesse Andre

Xanti
09.05.2006, 11:01
Weil ich oben die Option "-0\777" vergessen habe. Dabei hab ich sie erklärt...:think:

Egal, der Befehl müsste



perl -0\777 -pi -e 's/Text\nName/Tux\nTux/g' ptest


lauten. Normalerweise liest Perl Zeile für Zeile und kann deswegen Suchmuster, die über mehrere Zeilen gehen, nicht matchen. Mit der Option "-0\777" wird das File als ein grosser String eingelesen. Nachteil ist, dass das File nicht zu gross sein darf. Dann ist Wolfgangs Vorschlag mit sed zu bevorzugen.

Gruss, Xanti

ulukai
09.05.2006, 11:21
Super jetzt funktiniert es!
Ich dak euch...