sed: Einfügen unter dem letzten Vorkommen eines regexp

Fallout

Fallout

Doppel-As
Hi,

ich komme gerade mit meinem Problem nicht voran - auch das durchforsten von Google & Co. brachte mich bis jetzt noch nicht auf einen grünen Zweig. Vermutlich ist es eigentlich ganz simpel, nur ich komme nicht drauf :( :

ListenAddress abc21-123
# ListenAddress blablabla
#ListenAddress ::

soll hinterher werden zu:
# ListenAddress abc21-123
# ListenAddress blablabla
#ListenAddress ::
ListenAddress meinhost

Mein Ansatz sieht bis jetzt mal so aus:
Code:
sed -e 's/^[ \t]*\(ListenAddress[ \t]*\)/# \1/g' \
    -e 's/^[ \t]*#*[ \t]*\(ListenAddress[ \t].*\)/\1\nListenAddress meinhost/'

Was mir fehlt: er soll den Eintrag nur einmal, und zwar unter der zuletzt vorkommenden Zeile, einfügen (so macht er den Eintrag unter jeder Zeile). Kann mir dabei jemand helfen? Ich lasse mir auch gerne eine sinnvollere Neugestaltung des sed-Strings oder andere Alternativen zeigen. (Ich hab noch lange nicht alle RegEx und Aktionen intus - daher sieht der String vermutlich auch ein wenig "billig" aus :brav: )

Gruß Daniel
 
Hallo
Das ist nicht so trivial wie es ausschaut.
Welches Sed verwendest du?
Um festzustellen, was das letzte Vorkommen ist, musst du wohl:
die gesamte Datei erst in den Patternspace einlesen.
Next line holen N,
Bei der Letzten Zeile :
Dabei alle Listen mit #Listen ersetzen.
Dann das letzte Vorkommen mit deinem Replace ersetzen.
Und print;
Habe mal gebastelt, hoffe es geht:
Code:
$  cat Datei
#ListenAddress abc21-123
ListenAddress blablabla
# ListenAddress ::
#ListenAddress ::
anderer Text

sed -ne ':a;$!{N;ba;be};:e;{s/^[ \t]*#*[ \t]*\(ListenAddress [^\n]*\n\)/# \1/g;s/\n\(ListenAddress [^\n]*\)\n/\n# \1\n/g;s/\(.*\)\n#*ListenAddress[^\n]*\n\(.*\)$/\1\nListenAddress meinhost\n\2/g;p} ' Datei
# ListenAddress abc21-123
# ListenAddress blablabla
# ListenAddress ::
ListenAddress meinhost
anderer Text

Andere Bedingungen bitte selber testen, auch geht das mit GNU sed. Solaris sed wird wohl wieder streiken.

Gruß Wolfgang

Edit: Nachteil, ich fasse nur nicht auskommentierte Listen-Zeilen an.
Aber das zu korrigieren, habe ich jetzt keine Zeit.
Eventuell finden sich ja bessere sed-gurus hier. *g*
 
Zuletzt bearbeitet:
Hi,
Hallo
Welches Sed verwendest du?

GNU sed v4.1.4 (SuSE9.3)

Habe mal gebastelt, hoffe es geht:
Code:
sed -ne ':a;$!{N;ba;be};:e;
         {s/^[ \t]*#*[ \t]*\(ListenAddress [^\n]*\n\)/# \1/g;
          s/\n[U][B][ \t]*[/U][/B]\(ListenAddress [^\n]*\)\n/\n# \1\n/g;
          s/\(.*\)\n#*ListenAddress[^\n]*\n\(.*\)$/\1\nListenAddress meinhost\n\2/g;p}
        ' Datei

hm, funktioniert noch nicht so ganz:
Code:
fallout@server:~ # cat blubb
ListenAddress sshd
ListenAddress localhost
# ListenAddress localhost
  ListenAddress 32k23kjdsf:32kl:FD.j
        #               ListenAddress dlksfdsf:lk.slkds dssd.sdf.j.s  ###TABBED
ListenAddress home
         ListenAddress invalid.blubb ###TABBED
#ListenAddress ::


fallout@server:~ # sed -ne ':a;$!{N;ba;be};:e;{s/^[ \t]*#*[ \t]*\(ListenAddress [^\n]*\n\)/# \1/g;s/\n[B][ \t]*[/B]\(ListenAddress [^\n]*\)\n/\n# \1\n/g;s/\(.*\)\n#*ListenAddress[^\n]*\n\(.*\)$/\1\nListenAddress meinhost\n\2/g;p}' blubb
# ListenAddress sshd
# ListenAddress localhost
# ListenAddress localhost
  ListenAddress 32k23kjdsf:32kl:FD.j
        #               ListenAddress dlksfdsf:lk.slkds dssd.sdf.j.s  ###TABBED
# ListenAddress home
         ListenAddress invalid.blubb ###TABBED
#ListenAddress ::

U. a. stellt es wohl auch noch ein Problem dar, wenn der letzte .*ListenAddress-Eintrag in der letzten Zeile steht.
Und durch das fehlende [ \t]* in der 2. Ersetzungszeile wurden Zeilen mit '^[ \t]*ListenAddress' nicht auskommentiert.

Ich habe in der Zwischenzeit die folgende Konstellation verwendet:

Code:
sed -e 's/^[ \t]*\(ListenAddress[ \t]*\)/# \1/g;
        1,/^[ \t]*#*[ \t]*ListenAddress.*/s/\(^[ \t]*#*[ \t]*ListenAddress.*\)/ListenAddress sshd\n\1/;' Datei

Code:
fallout@server:~ # sed -e 's/^[ \t]*\(ListenAddress[ \t]*\)/# \1/g;1,/^[ \t]*#*[ \t]*ListenAddress.*$/s/\(^[ \t]*#*[ \t]*ListenAddress.*\)/ListenAddress meinhost\n\1/;' blubb
ListenAddress meinhost
#ListenAddress sshd
ListenAddress meinhost
# ListenAddress localhost
# ListenAddress localhost
# ListenAddress 32k23kjdsf:32kl:FD.j
        #               ListenAddress dlksfdsf:lk.slkds dssd.sdf.j.s  ###TABBED
# ListenAddress home
# ListenAddress invalid.blubb ###TABBED
#ListenAddress ::

womit der neue ListenAddress-Eintrag eben am Anfang statt am Ende eingebaut wird. Dummerweise tut er dies an der Testdatei vor und nach dem ersten gefundenen ListenAddress-Eintrag :think:.

Edit: Nachteil, ich fasse nur nicht auskommentierte Listen-Zeilen an.

Das ist schon ok so - bereits auskommentierte Zeilen sollen ja nicht nochmal auskommentiert werden.


Falls Dir oder anderen noch irgendwelche Hinweise oder Ideen einfallen, sind diese gerne gesehen :D

Gruß Daniel
 

Ähnliche Themen

Suchen und ersetzen in einer Textdatei

Probleme mit sed: im Text eine Zeile in Großbuchstaben ?

wie Regex für sed escapen?

sed macht mich wahnsinnig :-(

sed: zeichen einfügen?

Zurück
Oben