2012-04-11 29 views
4

eine Datei mit wiederholt kommentierten Zeilen zu haben mögen:Bash: wie sed zu verwenden, um nur das letzte Vorkommen in einer Datei zu ersetzen?

:

# ScriptAlias /cgi-bin/ "somepath" 
# ScriptAlias /cgi-bin/ "otherpath" 

ich eine Linie erst nach dem letzten Auftreten was

# ScriptAlias /cgi-bin/ "somepath" 
# ScriptAlias /cgi-bin/ "otherpath" 
ScriptAlias /cgi-bin/ "mypath" 

Dazu verwende ich diesen Befehl hinzufügen möchten

sed -i 's:^\(.*ScriptAlias /cgi-bin/.*\):\1 \nScriptAlias /cgi-bin/ "mypath":' file 

Aber dies führt meine Linie nach jedem Auftreten in der Zugabe wie:

# ScriptAlias /cgi-bin/ "somepath" 
ScriptAlias /cgi-bin/ "mypath" 
# ScriptAlias /cgi-bin/ "otherpath" 
ScriptAlias /cgi-bin/ "mypath" 

Wie kann ich sed sagen, nur das letzte Vorkommen zu ersetzen?

EDITED:
Wenn es keine Möglichkeit, es zu lösen ist mit sed (wie in den Kommentaren gesagt), bitte Alternativen bieten das gleiche Ergebnis zu erreichen, danke.



EDITED:
Die wiederholten Linien separeted und mit anderen Linien zwischen ihnen werden kann wie

# ScriptAlias /cgi-bin/ "somepath" 
# ScriptAlias /cgi-bin/ "otherpath" 

# ScriptAlias /cgi-bin/ "another-path" 
ScriptAlias /foo/ "just-jump" 
# ScriptAlias /cgi-bin/ "that's the last" 
+0

Dies ist kein Job für sed. Vielleicht awk, aber ich würde es in Python oder Perl tun. –

+0

@ MK.Ok .. Ich habe nach sed gefragt, weil ich es benutzt habe. Wenn es keine Möglichkeit gibt, es mit sed zu lösen, ist jede andere Methode willkommen. Danke –

+0

Oh, du kannst es mit sed machen, es ist meiner Meinung nach einfach nicht ideal. –

Antwort

6

Verwenden tac, damit Sie Ihre neue Linie des ersten Mal, wenn Sie das Muster sehen drucken:

tac file | awk '/ScriptAlias/ && ! seen {print "new line"; seen=1} {print}' | tac 
+0

Ich persönlich finde das eine ausgezeichnete Idee und es ist immer noch leicht zu lesen. Ich habe es ein wenig personalisiert und die Möglichkeit hinzugefügt, direkt in die Datei zu schreiben, (gibt es eine Möglichkeit, Ihre Lösung mit interaktiv -i zu verwenden?). Mein Befehl ist schließlich 'tac $ file | awk '/ ScriptAlias ​​\/cgi-bin \ // &&!gesehen {print "ScriptAlias ​​/ cgi-bin/\" meinpfad \ ""; gesehen = 1} {Druck} '| tac> "/ var/lock/$ {Datei}" && mv "/ var/lock/$ {Datei}" "$ {Datei}" ' –

+0

Kann nicht direkt in die Eingabedatei schreiben. Sie müssen eine temporäre Datei verwenden (wie Sie es getan haben). Das ist, was 'sed -i' im Hintergrund tut. –

1

Alternative mit awk:

awk '/ScriptAlias \/cgi-bin\//{x=NR} {a[NR]=$0;}END{for(i=1;i<=NR;i++){if(i==x+1)print "$$$here comes new line$$$"; print a[i];}}' file 

Test:

kent$ echo "# ScriptAlias /cgi-bin/ "somepath" 
fooo 
# ScriptAlias /cgi-bin/ "otherpath" 
bar 
"|awk '/ScriptAlias \/cgi-bin\//{x=NR} {a[NR]=$0;}END{for(i=1;i<=NR;i++){if(i==x+1)print "$$$here comes new line$$$"; print a[i];}}' 

Ausgang:

# ScriptAlias /cgi-bin/ somepath 
fooo 
# ScriptAlias /cgi-bin/ otherpath 
$$$here comes new line$$$ 
bar 
0
tail -r temp | awk '{line="yourline"}{if($0~/ScriptAlias/&&last==0){print line"\n"$0;last=1}else print}' | tail -r 

unten getestet:

krithika.337> cat temp 
# ScriptAlias /cgi-bin/ "somepath" 
# ScriptAlias /cgi-bin/ "otherpath" 
# ndmxriptAlias /cgi-bin/ "otherpath" 
# ScriptAlias /cgi-bin/ "otherpath" 
# bdjiptAlias /cgi-bin/ "otherpath" 
krithika.338> tail -r temp | awk '{line="yourline"}{if($0~/ScriptAlias/&&last==0){print line"\n"$0;last=1}else print}' | tail -r 
# ScriptAlias /cgi-bin/ "somepath" 
# ScriptAlias /cgi-bin/ "otherpath" 
# ndmxriptAlias /cgi-bin/ "otherpath" 
# ScriptAlias /cgi-bin/ "otherpath" 
yourline 
# bdjiptAlias /cgi-bin/ "otherpath" 
krithika.339> 
+0

GNU Tail (von Coreutils) hat keine' -r' Option. – yazu

0

Es ist eine Aufgabe für den Editor.

ex input_file << "DONE" 
/ScriptAlias \/cgi-bin\/ "otherpath" 
a 
ScriptAlias /cgi-bin/ "mypath" 
. 
:1 
/ScriptAlias \/cgi-bin\/ "another-path" 
a 
ScriptAlias /cgi-bin/ "just-jump" 
. 
:x 
DONE 

Im letzten Modus.

ex input_file << "DONE" 
$ 
?ScriptAlias \/cgi-bin\/ "otherpath" 
a 
ScriptAlias /cgi-bin/ "mypath" 
. 
$ 
?ScriptAlias \/cgi-bin\/ "another-path" 
a 
ScriptAlias /cgi-bin/ "just-jump" 
. 
:x 
DONE 
Verwandte Themen