【发布时间】:2020-11-16 02:50:27
【问题描述】:
我正在使用下面的 sed 命令来替换一个字符串
sed -i "s|find string|replace string|g" inputfile
但它会取代所有的出现。 (我认为g 是为Global 替换)
如何使用 sed 或 grep 或 awk 仅对指定次数进行字符串替换,即 10 次或 15 次。 .?
【问题讨论】:
我正在使用下面的 sed 命令来替换一个字符串
sed -i "s|find string|replace string|g" inputfile
但它会取代所有的出现。 (我认为g 是为Global 替换)
如何使用 sed 或 grep 或 awk 仅对指定次数进行字符串替换,即 10 次或 15 次。 .?
【问题讨论】:
你可以这样做:
perl -pe '$i++ while($i < 10 && s/pattern/replace/)' input
在 awk 中:
awk '{ while( i< c && sub( "pattern", "replace" )) i+=1}1' c=10 input
【讨论】:
-p 使 perl 循环其输入并打印每一行,-e 只是指定要运行的代码(-e 之后的下一个参数)。
i+=1 与i++ 相同
i++ 是一个表达式,但 i+=1 是一个语句。作为副作用,i++ 增加了i,因此从这个意义上说,它们在语义上相似,但在赋值的 RHS 上使用时它们的评估不同。我发现使用i+=1 更具可读性,因为它使意图更清晰。
pur sed 但最好不要使用 sed 来解决此类问题,最好使用 awk(或 perl)
sed -n -e '1h;1!H
$ {s/.*//;x
t loop
:loop
s|find string|replace string|
t occur
b print
:occur
x
s/$/o/
t count
:count
s/o\{10\}/&/
x
t print
b loop
:print
p
}' YourFile
s/o\{10\}/&/ 中的 10 是想要的出现次数。将s//;t label 用作if/goto。没有'else',很多s//;t。
首先,需要将整个文件加载到工作缓冲区中(默认情况下每行 sed 工作)。此外,它使用辅助缓冲区作为计数器。
【讨论】:
sed ':loop; x; s/o\{10\}/&/; x; t; s/pattern/replace/; t count; b; :count; x; s/^/o/; x; t loop;'
这是另一个awk 版本。
awk 'c && sub("pattern","replace") {c--}1' c=2 file
【讨论】:
这是一个更易读的awk 版本:
awk '{for(i=0; i<15; i++) sub("pattern", "replacement"); print $0}' file
【讨论】: