如何仅替换文件中的最后一个匹配项?

问题描述 投票:0回答:4

有一个包含重复注释行的文件,例如:

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

我只想在最后一次出现之后添加一行,导致

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

为此,我使用以下命令:

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

但这会导致每次出现后添加我的行,例如:

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

如何告诉 sed 仅替换最后一次出现的情况?

如果使用 sed 无法解决(如评论中所述),请提供达到相同结果的替代方案,谢谢。

重复的线可以分开,并在它们之间插入其他线,就像

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

# ScriptAlias /cgi-bin/ "another-path"
ScriptAlias /foo/ "just-jump"
# ScriptAlias /cgi-bin/ "that's the last"
bash shell awk sed
4个回答
6
投票

使用tac,以便您在第一次看到图案时打印新行:

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

1
投票

与 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

测试:

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];}}'

输出:

# 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

测试如下:

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
投票

这是编辑的任务。

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

在最后出现模式。

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
© www.soinside.com 2019 - 2024. All rights reserved.