在每行找到第 n 个匹配后替换模式?

mun*_*ish 6 shell sed awk shell-script

我有一个包含行的文件:

india;austria;japan;chile
china;US;nigeria;mexico;russia
Run Code Online (Sandbox Code Playgroud)

我想用 eg 替换每行出现的所有分号;NEW;,但只从第二次出现开始。结果应如下所示:

india;austria;NEW;japan;NEW;chile
china;US;NEW;nigeria;NEW;mexico;NEW;russia
Run Code Online (Sandbox Code Playgroud)

我用 gsub 试过这个,但它替换了所有的出现: awk '/;/{gsub(/;/,";NEW;") }{print}'

man*_*ork 8

awk解决方案是更长的时间,但更容易使它通用:

awk -F\; '{for(i=1;i<NF;i++)printf"%s;%s",$i,(i>=2)?"NEW;":"";print$NF}' replacefile
Run Code Online (Sandbox Code Playgroud)

也可以这样做,使用命令sed进行循环t并始终将第二个(或任何您想要的)分隔符替换为某个临时标记(通常为\n):

sed ':b;s/;/\n/2;tb;s/\n/;NEW;/g' replacefile
Run Code Online (Sandbox Code Playgroud)


gle*_*man 8

GNU sed 的s///命令有一个标志可以执行此操作:

sed 's/;/;NEW;/2g' <<END
india;austria;japan;chile
china;US;nigeria;mexico;russia
END
Run Code Online (Sandbox Code Playgroud)

产出

india;austria;NEW;japan;NEW;chile
china;US;NEW;nigeria;NEW;mexico;NEW;russia
Run Code Online (Sandbox Code Playgroud)

请参阅https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-Command

s命令之后可以进行下列标志的零个或多个:

g

将替换应用于正则表达式的所有匹配项,而不仅仅是第一个。

数字

只有更换号码的正则表达式的个匹配。注意:posix 标准没有指定混合使用g数字修饰符时会发生什么,目前在 sed 实现中没有广泛同意的含义。用于GNU sed的,相互作用被定义为:忽略之前比赛日,然后匹配并从替换所有比赛在th。

...

(强调我的)

  • 伟大的!我从来没有注意到你可以结合 `g` 和数字标志。 (2认同)