Suchen und Ersetzen (per sed mit regex?)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
smo
Beiträge: 489
Registriert: 19.12.2005 16:34:40
Lizenz eigener Beiträge: MIT Lizenz

Suchen und Ersetzen (per sed mit regex?)

Beitrag von smo » 05.02.2006 00:44:24

Hallo,

ich möchte ein txt.file manipulieren, habe sowas allerdings noch nie per scripting gemacht. Aus Zeilen mit dem Muster
'mozillaPostalAddress2:'97080 Wuerzburg'
sollen die zwei Zeilen
'mozillaHomePostalCode: 97080
mozillaHomeLocalityName: Wuerzburg'
werden.


In einem anderen Post habe ich bereits sed entdeckt:
sed -e test.txt s/sucheNach/ErsetzeDurch/g INPUTFILE > OUTPUTFILE

Mit dem Ausdruck 'mozillaPostalAddress2: ([0-9]{5}) ([A-Za-z]*)' sollte ich die obige Zeile erwischen (also das sucheNach). Wie kann ich jetzt auf die durch die runden Klammern definierten Gruppen zugreifen um PLZ und Ort in die neue Zeile zu schreiben?

Oder würdet ihr das mit ganz anderen Tools lösen?

smo

zaarkov
Beiträge: 123
Registriert: 14.08.2003 11:08:51

Re: Suchen und Ersetzen (per sed mit regex?)

Beitrag von zaarkov » 05.02.2006 01:20:29

smo hat geschrieben:
In einem anderen Post habe ich bereits sed entdeckt:
sed -e test.txt s/sucheNach/ErsetzeDurch/g INPUTFILE > OUTPUTFILE

Mit dem Ausdruck 'mozillaPostalAddress2: ([0-9]{5}) ([A-Za-z]*)' sollte ich die obige Zeile erwischen (also das sucheNach). Wie kann ich jetzt auf die durch die runden Klammern definierten Gruppen zugreifen um PLZ und Ort in die neue Zeile zu schreiben?

smo
du kannst die ausdruecke in runden klammern in ErsetzeDurch \1 ersetzen.
die naechsten klammern mit \2, usw.

gruss
zaarkov

fuzzy
Beiträge: 1021
Registriert: 04.10.2003 12:15:52

Beitrag von fuzzy » 05.02.2006 10:20:29

Hallo smo,
also mit "awk" ist es auch möglich.
...meine Lösung ist bestimmt nicht elegant, ich hoffe auf elegantere Lösungen :wink:
Ich bin mir nicht so sicher welche Anführungszeichen in der Datei sind und welche nicht, mit den [ code ]-Tags lässt sich soetwas deutlicher darstellen.

Code: Alles auswählen

fuzzy@sid:/tmp$ cat test.txt 
mozillaPostalAddress2:'97080 Wuerzburg

fuzzy@sid:/tmp$  sed "s/'/ /" test.txt | awk ' {print "mozillaHomePostalCode:"$2 "\nmozillaHomeLocalityName:"$3}'
mozillaHomePostalCode:97080
mozillaHomeLocalityName:Wuerzburg
Hilft Dir das weiter?

http://www.linuxfibel.de/kapitel7.htm

Gruß fuzzy

smo
Beiträge: 489
Registriert: 19.12.2005 16:34:40
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von smo » 05.02.2006 18:13:53

Leider tut's noch nicht so wie ich will. Nochmal zur Klarstellung (da oben vom mir falsch angegeben), die Quelldatei (test.ldif) beinhaltet diese Zeile:

Code: Alles auswählen

mozillaPostalAddress2: 97080 Wuerzburg 
Daraus soll werden (test2.ldif):

Code: Alles auswählen

mozillaHomePostalCode: 97080
mozillaHomeLocalityName: Wuerzburg

Das habe ich bisher:

Code: Alles auswählen

# /bin/bash

sucheNach='mozillaPostalAddress2: ([0-9]{5}) ([A-Za-z]*)'
plz='mozillaHomePostalCode: '
ort='mozillaHomeLocalityName: '
ersetzeDurch=$plz'\1\n'$ort'\2'

echo
echo $sucheNach
echo $plz
echo $ort
echo $ersetzeDurch
echo

sed s/$sucheNach/$ersetzeDurch/g test.ldif > test2.ldif
Raus kommt:

Code: Alles auswählen

mozillaPostalAddress2: ([0-9]{5}) ([A-Za-z]*)
mozillaHomePostalCode:
mozillaHomeLocalityName:
mozillaHomePostalCode: \1\nmozillaHomeLocalityName: \2

sed: -e Ausdruck #1, Zeichen 24: unterminated `s' command
Er stört sich also anscheinend an der geöffneten Klammer im regulären Ausdruck? Ich denke ich mache beim Verwenden der Variablen was falsch. Nur was?

smo
Zuletzt geändert von smo am 05.02.2006 19:52:09, insgesamt 1-mal geändert.

fuzzy
Beiträge: 1021
Registriert: 04.10.2003 12:15:52

Beitrag von fuzzy » 05.02.2006 18:47:51

Code: Alles auswählen

fuzzy@sid:/tmp$ ll *ldif
-rw-r--r-- 1 fuzzy fuzzy 40 2006-02-05 18:35 test.ldif

fuzzy@sid:/tmp$ cat test.ldif 
mozillaPostalAddress2: 97080 Wuerzburg 

fuzzy@sid:/tmp$ /tmp/postcode.sh 

fuzzy@sid:/tmp$ ll *ldif
-rw-r--r-- 1 fuzzy fuzzy 64 2006-02-05 18:45 test2.ldif
-rw-r--r-- 1 fuzzy fuzzy 40 2006-02-05 18:35 test.ldif

fuzzy@sid:/tmp$ cat test2.ldif 
mozillaHomePostalCode: 97080
mozillaHomeLocalityName: Wuerzburg

fuzzy@sid:/tmp$ cat /tmp/postcode.sh 
#!/bin/sh

VORHER="/tmp/test.ldif"
NACHHER="/tmp/test2.ldif"
/usr/bin/awk '{print "mozillaHomePostalCode: "$2 "\nmozillaHomeLocalityName: "$3}' $VORHER  > $NACHHER
PS: leider verstehe ich Dein Script nicht so richtig - muss nix heißen, so viel Plan habe ich leider nicht..
Es wird aber immer empfohlen den absoluten pfad anzugeben, also "/bin/echo" statt "echo" und so weiter...

ulf
Beiträge: 39
Registriert: 22.09.2002 13:00:52

Beitrag von ulf » 06.02.2006 11:40:52

smo hat geschrieben:Leider tut's noch nicht so wie ich will. Nochmal zur Klarstellung (da oben vom mir falsch angegeben), die Quelldatei (test.ldif) beinhaltet diese Zeile:

Code: Alles auswählen

mozillaPostalAddress2: 97080 Wuerzburg 
Daraus soll werden (test2.ldif):

Code: Alles auswählen

mozillaHomePostalCode: 97080
mozillaHomeLocalityName: Wuerzburg

Das habe ich bisher:

[...]

Er stört sich also anscheinend an der geöffneten Klammer im regulären Ausdruck? Ich denke ich mache beim Verwenden der Variablen was falsch. Nur was?

smo

Code: Alles auswählen

#! /bin/bash

sucheNach='mozillaPostalAddress2: \([0-9]\{5\}\) \([A-Za-z]*\)'
plz='mozillaHomePostalCode: '
ort='mozillaHomeLocalityName: '
ersetzeDurch=$plz'\1\n'$ort'\2'

echo
echo "suche  : $sucheNach"
echo "plz    : $plz"
echo "ort    : $ort"
echo "ersetze: $ersetzeDurch"  # hier sinnlos, da \1, \2 und \n nicht
echo                           # definiert (für \n: echo -e)

sed -ne "s/$sucheNach/$ersetzeDurch/p" test.ldif | tee test2.ldif
Gruß,
Ulf

smo
Beiträge: 489
Registriert: 19.12.2005 16:34:40
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von smo » 16.02.2006 20:20:58

Sorry für die lange Reaktionszeit, aber die letzten Tage waren recht stressig.. ulfs Beispiel hat mir inzwischen den Durchbruch gebracht. :)

Letztendlich sieht's jetzt so aus:

Code: Alles auswählen

#! /bin/bash

sucheNach='mozillaHomePostalAddress2: \([0-9]\{5\}\) \([A-Za-z]*\)'
plz='mozillaHomePostalCode: '
ort='mozillaHomeLocalityName: '
ersetzeDurch=$plz'\1\n'$ort'\2'

echo
echo "suche  : $sucheNach"
echo "plz    : $plz"
echo "ort    : $ort"
echo "ersetze: $ersetzeDurch"
echo                                         

sed -e "s/$sucheNach/$ersetzeDurch/g" my.ldif | tee myNew.ldif

Unterschiede zu ulfs Variante:

1. SucheNach: 'mozillaHomePostalAddress2' statt 'mozillaPostalAddress2' (mein Fehler)
2. sed: n-Option weggelassen weil ich auch die unveränderten Zeilen in test2.ldif schreiben will
3. sed: g für global -> alle passenden Textteile ersetzen
4. sed: Verzicht auf p -> Inhalt wird komplett ausgegeben

Danke an alle!

smo

Antworten