str="I want to abc replace a word abc in a sentence abc of file abc by giving abc specifying a abc multiple abc range to abc the sed abc command abc."
上面的字符串 str 中有单词“abc”10倍发生,我想替换“abc”发生在2-4名时间和6-8名使用 sed 命令来处理单词“xyz”。
对字符串 str 执行 sed 命令后,str 应该如下所示:
str="I want to abc replace a word xyz in a sentence xyz of file xyz by giving abc specifying a xyz multiple xyz range to xyz the sed abc command abc."
答案1
我不确定它是否聪明,但这是我的 GNU sed 解决方案:
sed 's/abc/nonABC/5;s/abc/nonABC/8g;s/abc/xyz/2g;s/nonABC/abc/g' <<<"$str"
解释:
sed '
s/abc/nonABC/5; # replace only 5th occurrence of 'abc' word with another word (i, e: 'nonABC')
s/abc/nonABC/8g; # replace 8th to the next occurrences of 'abc' with another word too
s/abc/xyz/2g; # replace all occurrences of 'abc' word start from 2th place
s/nonABC/abc/g # get back the all changed 'abc' from 'nonABC'
' <<<"$str" # from 'str' as input
当然还有awk
聪明的做法:
awk '{printf ( 2<=NR && NR<=8 && NR!=5 )?$0"xyz":$0RS}' RS='abc' <<<"$str"
解释:
RS='abc'
将 'abc' 定义为R记录年代分离器- 如果否数量Record 介于 2 和 8 之间
2<=NR && NR<=8
但不等于 5NR!=5
,则打印当前记录$0
和替换词xyz
,否则,打印记录及其abc
本身。你可以$0"abc"
代替使用$0RS.
如果你的范围如下: [(2-4),(8-10),(12-15),(18-20),(26-29) ...]你在评论中提到thenawk
是这个任务的最佳命令。你只需要将范围指定为多个条件:
( (2<=NR && NR<=4) || (8<=NR && NR<=10) || (12<=NR && NR<=15) || (18<=NR && NR<=20) || (26<=NR && NR<=29) || (...) )
答案2
另一种方法是借助括号扩展,你可以这样做:
sed '-es/abc/xyz/'{8..6} '-es/abc/xyz/'{4..2} <<<"$str"
请注意,范围应该始终是max
第一个,{max#..min#}
甚至应该首先指定最大范围。
您还可以指定应在{x,y,z}
格式中替换的位置范围,其中数字应该是x>y>z
:
sed '-es/abc/xyz/'{8,6,4,2} <<<"$str"
请注意,如果您使用相同的数字,{x,x}
则会导致问题并会x
一次又一次地替换位置(顺便说一下,还有s/abc/xyz/X
另一种选择,X
即位置编号)。