问题
Having a file containing repeated commented lines like:
# ScriptAlias /cgi-bin/ "somepath"
# ScriptAlias /cgi-bin/ "otherpath"
I want to add a line only after the last occurence resulting in
# ScriptAlias /cgi-bin/ "somepath"
# ScriptAlias /cgi-bin/ "otherpath"
ScriptAlias /cgi-bin/ "mypath"
To do so I'm using this command:
sed -i 's:^\(.*ScriptAlias /cgi-bin/.*\):\1 \nScriptAlias /cgi-bin/ "mypath":' file
But this results in adding my line after each occurence like:
# ScriptAlias /cgi-bin/ "somepath"
ScriptAlias /cgi-bin/ "mypath"
# ScriptAlias /cgi-bin/ "otherpath"
ScriptAlias /cgi-bin/ "mypath"
How can I tell sed to replace only the last occurence?
EDITED:
If there's no way to solve it using sed (as said in comments), please provide alternatives reaching the same result, thanks.
EDITED:
The repeated lines can be separeted and with other lines between them like
# ScriptAlias /cgi-bin/ "somepath"
# ScriptAlias /cgi-bin/ "otherpath"
# ScriptAlias /cgi-bin/ "another-path"
ScriptAlias /foo/ "just-jump"
# ScriptAlias /cgi-bin/ "that's the last"
回答1:
Use tac so you print your new line the first time you see the pattern:
tac file | awk '/ScriptAlias/ && ! seen {print "new line"; seen=1} {print}' | tac
回答2:
alternative with 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];}}'
output:
# ScriptAlias /cgi-bin/ somepath
fooo
# ScriptAlias /cgi-bin/ otherpath
$$$here comes new line$$$
bar
回答3:
tail -r temp | awk '{line="yourline"}{if($0~/ScriptAlias/&&last==0){print line"\n"$0;last=1}else print}' | tail -r
tested below:
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>
回答4:
It is a task for the 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
In last occurence mode.
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
来源:https://stackoverflow.com/questions/10106292/bash-how-to-use-sed-to-replace-only-the-last-occurence-in-a-file