0

File: test

cat cat
dog cat
dog puppy
dog cat

Command:

sed -i 's/dog/big_dog/2' test

According to the explanation here: http://www.grymoire.com/Unix/Sed.html#uh-8 the output of the code should have been:

cat cat
dog cat
big_dog puppy
dog cat

But the file remains unchanged for me.

What am I doing wrong?

Bishwas Mishra
  • 1,235
  • 1
  • 12
  • 25
  • That's not what I am asking. Anyway I told "the file remains unchanged". But it should have changed. – Bishwas Mishra Jun 04 '18 at 09:45
  • question is how is this question different from the one marked as duplicate asked by you.. – Sundeep Jun 04 '18 at 09:45
  • That question is confusing. This should be clear. Here I am asking why sed is not working as it should have worked. – Bishwas Mishra Jun 04 '18 at 09:46
  • Why do people flag a question. The questioner is someone who is in confusion and needs help. There should be some degree of freedom to make mistakes in asking the question the right way. – Bishwas Mishra Jun 04 '18 at 09:50
  • 1
    by default sed works line by line using newline character to distinguish lines.. what you've tried would only try to replace 2nd occurrence in a given line, not across whole file.. in your given example input, no line has 2 or more occurrences of `dog`, so file will remain unchanged – Sundeep Jun 04 '18 at 09:50
  • 2
    Look, if you use `sed 's/cat/dog/2' test` your first line will turn into `cat dog` because `2` means *only replace the second match **on a line***. – Wiktor Stribiżew Jun 04 '18 at 09:50
  • 1
    Cool. Makes sense now. – Bishwas Mishra Jun 04 '18 at 09:51

1 Answers1

0

Looks like awk has a solution:

awk '/dog/{c++;if(c==2){sub("dog","big_dog");c=0}}1' test

Source: https://www.linuxquestions.org/questions/programming-9/replace-2nd-occurrence-of-a-string-in-a-file-sed-or-awk-800171/

Bishwas Mishra
  • 1,235
  • 1
  • 12
  • 25
  • 1
    this would replace every 2nd line containing `dog`, is that what you want? if not, use `awk '/dog/ && ++c==2{sub("dog","big_dog")} 1'` – Sundeep Jun 04 '18 at 09:52
  • Ultimately I want the replace the nth occurance. How to substitute "dog" with a variable? – Bishwas Mishra Jun 04 '18 at 09:56
  • 1
    I'd recommend to use learning resources mentioned in https://stackoverflow.com/tags/awk/info to get basic understanding.. `awk -v w='dog' -v r='big_dog' '$0 ~ w && ++c==2{sub(w, r)} 1'` might help (but you might have more doubts which I'd rather not clarify in comments), see also https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script for details.. – Sundeep Jun 04 '18 at 10:00
  • 1
    Cool. Thanks for the link. Learning material works for me. – Bishwas Mishra Jun 04 '18 at 10:01
  • The code in your answer doesn't do what you asked for in your question (replace the 2nd occurrence) and there's a more concise way to write what it does do (replace every other occurrence) and it's using a string as a dynamic regexp when it should be using a regexp literal and you shouldn't be testing for the same regexp twice. In short, it is wrong no matter what it is you're trying to do. – Ed Morton Jun 07 '18 at 12:34