如何使用sed仅替换第二个匹配行

3
$ cat file
cat cat
dog cat
dog puppy
dog cat

使用sed:
$ sed 's/dog/big_dog/' my_file > new_file
$ cat new_file
cat cat 
big_dog cat
big_dog puppy
big_dog cat

我的目标是仅将第二个dog替换为big_dog,但使用以下代码未能实现:

$ sed 's/dog/big_dog/2' my_file > new_file
cat
dog cat
dog puppy
dog cat

我如何只替换第二次出现的内容,即:

cat
dog cat
big_dog puppy
dog cat

2
请尽可能在一个帖子中提出您的所有要求。请始终尝试选择任何提供的答案作为正确答案来关闭主题,谢谢。 - RavinderSingh13
更新了问题。 - Bishwas Mishra
第一件事是您没有在代码标签中涵盖您的示例(请始终这样做)。第二,始终尝试尊重已回答的人,通过在相应的评论中告诉他们他们的代码是否有效,SO仅用于指导而不是免费服务。希望这可以帮助您。 - RavinderSingh13
“covered your samples in code tags” 是什么意思? - Bishwas Mishra
这是你的答案:sed -i '0,/dog/! {0,/dog/ s/dog/big_dog/}' my_file - Hashbrown
4个回答

7

sed用于替换第二个出现的内容的命令为:

sed "/dog/ {n; :a; /dog/! {N; ba;}; s/dog/big_dog/; :b; n; $! bb}" your_file

说明:

/dog/ {           # find the first occurrence that match the pattern (dog)
  n               # print pattern space and read the next line
  :a              # 'a' label to jump to
  /dog/! {        # if pattern space not contains the searched pattern (second occurrence)
    N             # read next line and add it to pattern space
    ba            # jump back to 'a' label, to repeat this conditional check
  }               # after find the second occurrence...
  s/dog/big_dog/  # do the substitution
  :b              # 'b' label to jump to
  n               # print pattern space and read the next line
  $! bb           # while not the last line of the file, repeat from 'b' label
}

请注意,最后三个命令是在找到第二次出现后打印文件的剩余部分所必需的,否则替换可能会针对每个搜索模式的偶数次出现重复执行。

6

如评论中所讨论的那样,这个替换操作是在第二行上进行的匹配:

$ sed '2s/dog/big_dog/' your_file
dog cat
big_dog puppy
dog cat

要使用sed替换第二个匹配项,请使用:

sed ':a;N;$!ba;s/dog/big_dog/2'   your_file_with_foo_on_first_row_to_demonstrate
foo
dog cat
big_dog puppy
dog cat

工作得非常完美。你能给我指一下这个的文档吗? - Bishwas Mishra
请在这里查找“4 Addresses: selecting lines”部分。 - James Brown
1
@BishwasMishra,试试我的awk代码,我在其中放置了一个变量,它可以有出现次数,然后它将根据出现次数更改到该行,如果这有帮助,请告诉我。此外,请始终在您的帖子中一次性提及所有要求。 - RavinderSingh13
第二行是对它进行替换,而不是替换第二次出现的内容,对吗? - Kent
1
@RavinderSingh13 或许我应该道歉... 我发表了那个评论(只是在做第二行的替换),关于这个答案。然而,你认为我评论了你的评论... 在我读了你的评论之后,我以为那是James的回复... 所以... 你再次解释了你的awk事情在这个sed答案下面.. ^_* - Kent
显示剩余3条评论

3
以下的 awk 也可能会对你有所帮助。
awk -v line=2 '$1=="dog" && ++count==line{$1="big_dog"} 1'  Input_file

如果要将输出保存到输入文件本身,则在上面的代码中添加> temp_file && mv temp_file Input_file说明:
awk -v line=2 '             ##Creating an awk variable line whose value is 2 here.
$1=="dog" && ++count==line{ ##Checking condition if $1 is dog and increasing variable count value is equal to value of line(then do following)
  $1="big_dog"}             ##Assigning $1 to big_dog here.
1                           ##awk works on method of condition then action so by mentioning 1 I am making condition TRUE here so by default action print of line will happen.
'  Input_file               ##Mentioning Input_file here.

-1
使用以下命令将第二行中的单词“dog”替换为“big_dog”。
# sed -i '2 s/dog/big_dog/g' my_file
# cat my_file
Output:-
dog cat
big_dog puppy
dog cat

如果您想从第二个替换到第三个,可以使用以下命令:

# sed -i '2,3 s/dog/big_dog/g' my_file

2
希望它不是特定于某一行的。 - Bishwas Mishra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接