如何编写 a sed
(或awk
,或两者),它将采用以下内容:
echo '1 aa 2 2 3 bb 5 bb 2 5' | sed/awk ...
并且只替换第n次出现的字符串?例如,第三次出现2
或第二次出现bb
?
因此,预期的输出将是(例如,当替换第二次出现的 时)bb
:replaced
1 aa 2 2 3 bb 5 replaced 2 5
输入字符串、替换字符串,n
可以是任意输入。
答案1
用于sed
更改第二次出现的bb
$ sed 's/bb/new-bb/2' file
1 aa 2 2 3 bb 5 new-bb 2 5
或更改第三次出现的 2
$ sed 's/2/12/3' file
1 aa 2 2 3 bb 5 bb 12 5
答案2
要更改行中第 n 个sed
出现的位置,语法为s/pattern/replacement/3
as已经由@HatLess展示。
要更改整个输入中的第 n次perl
出现,您可以使用:
perl -pse 'if($n>0) {s{pattern}{--$n ? $& : "replacement"}ge}' -- -n=3
答案3
和awk
你一起可以做:
awk -v str='bb' -v pos=2 -v rplc='newBB' '
{
strPos=0
for(i=1; i<=NF; i++)
if($i==str && (++strPos==pos) ) { $i=rplc; break }
}1' infile
输出:
1 aa 2 2 3 bb 5 newBB 2 5
注意:上面假设只有一个字符作为字段分隔符(默认:空格或制表符),否则连续的字段分隔符将挤成一个,或者您可以强制 awk 分别匹配每个单个字段分隔符(因此 FS 必须强制作为正则表达式模式):
awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
{
strPos=0
for(i=1; i<=NF; i++)
if($i==str && (++strPos==pos) ) { $i=rplc; break }
}1' infile
注意:\t
如果字段分隔符是空格字符,请更改为空格字符。
要更改整个输入中的第 n次出现(但我假设字段分隔符是制表符):
awk -F'[\t]' -v OFS='\t' -v str='bb' -v pos=2 -v rplc='newBB' '
strPos!=2{
for(i=1; i<=NF; i++)
if($i==str && (++strPos==pos) ) { $i=rplc; break }
}1' infile
答案4
我们可以用sed
一个命令来完成这两个任务:
echo "1 aa 2 2 3 bb 5 bb 2 5"|sed -e "s/2/kop/3" -e "s/bb/pp/2"
此命令将替换第三次出现的2
withkop
和第二次出现的bb
with pp
。