0

I have a large text file that needs some changes. I need to do this by first locating lines that have a particular common string, and then editing the line directly after that. So for example, if I ran this grep command:

# grep -A1 important_string gianttextfile.txt
important_string
change_this

I would want to first locate important_string, and then modify change_this to be something else, several times throughout a document. I cannot just modify all change_this entries because many of them need to stay as they are, it's just the ones following this particular string that I need to change.

What would be the best way to accomplish this?

3
  • Should a line just after important_string be tested for important_string: before substitution? after substitution? only if there was no substitution? or never? – Kamil Maciorowski Oct 8 '20 at 17:17
  • @KamilMaciorowski I'm maybe not understanding what you're asking. There's two possible values that can follow important_string. change_this is one, new_value is the other (there's some other junk on that line too but that can stay as it is). What I need is effectively # sed -i 's/change_this/new_value/' file.txt but applied only to the line immediately following each occurrence of important_string. – Kefka Oct 9 '20 at 13:58
  • These are example strings, not your actual strings, right? If the actual strings were foo, ofa and f respectively, and the input was foo, ofafoo, foofa, ofaoo, ofa (5 lines), then ofafoo should be changed to ffoo. But there's also foo there, before and after the replacement. So should the third line be changed? If yes, then foo in the third line will disappear. Should the fourth line be changed because of the disappearing foo in the third? If yes, then foo will appear in the fourth. Should the fifth line be changed because of the appearing foo? – Kamil Maciorowski Oct 9 '20 at 14:38
2
sed '/important_string/ {n;s/change_this/new_value/}'

Notes:

  • Remember important_string and change_this are parsed as regular expressions.

  • Any line where s is performed is not tested for important_string, so it cannot trigger s for the next line. This means a snippet like this:

    …
    foo                #  this line does not trigger s for the next line
    important_string   #  this line triggers s for the next line
    important_string   #  s is performed here
    change_this        #  s in not performed here
    …
    

    will not change. A variant that always tests for important_string is

    sed ':start; /important_string/ {n;s/change_this/new_value/;b start}'
    
  • If s could make important_string appear or disappear then you may want to test for important_string before substitution and/or after substitution; or not to test if s made a successful substitution. This answer does not cover all these cases.

  • Use s/…/…/g if needed.

  • Use sed -i … file if needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.