Reputation: 16992
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 occurrence 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?
If there's no way to solve it using sed (as said in comments), please provide alternatives reaching the same result, thanks.
The repeated lines can be separated 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"
Upvotes: 5
Views: 6563
Reputation: 7630
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
Upvotes: 0
Reputation: 67221
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>
Upvotes: 0
Reputation: 246807
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
Upvotes: 6
Reputation: 195059
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
Upvotes: 1