How to find specific lines in a file and then replace a word from those lines keeping everything else intact using vi/vim editor

Viewed 84

I have a random file with a bunch of lines. Snippet:

lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not simply random text cold
lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not simply random text hot
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout
There are many variations of passages of Lorem Ipsum available
lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not simply random text tea
There are many variations of passages of Lorem Ipsum available
lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not simply random text bee

etc

I want to match every line starting with lorium0{([y])} and then replace simply with very using the vi or vim editor (Preferably with vi). Would like to accomplish this with a 1 line command.

  1. Find Regex match to filter out unwanted lines
  2. Find word simply and replace with very

ie.:

lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not simply random text bee
Becomes:
lorium0{([y])} Contrary to popular belief, Lorem Ipsum is not very random text bee

Trying:

:1,$ s\(lorium0[^ ].*\)\1\(simply\)\2\1: very\2g 

But having difficulty formatting the command and understanding capture groups in substitution.

Thanks.

2 Answers

Use :g with a pattern to restrict the lines on which the replacement is made. For example:

:g/^lorium0{(\[y\])}/s/simply/very

This is the classic solution, following the pattern g/pattern/command. (When "pattern" is replaced by "re" (regex) and the command is "p" (print), this becomes g/re/p and you see why the popular command is named grep.) The buffer is searched globally, and the command is applied to any line which matches the pattern. For more information, use :help :global.

You can use

:%s/^lorium0{(\[y])}.*\zs\<simply\>/very/g

Or,

:%s/\(^lorium0{(\[y])}.*\)\@<=\<simply\>/very/g

Details:

  • ^ - start of string/line
  • lorium0{(\[y])} - a literal lorium0{([y])} text
  • .* - any zero or more chars other than line break chars as many as possible
  • \zs - the text before is just context, the match starts at this point
  • OR \(^lorium0{(\[y])}.*\)\@<= matches a location that is immediately preceded with the ^lorium0{(\[y])}.* pattern
  • \<simply\> - a whole word simply (\< and \> are word boundaries).

Or, you may use a group (in the regex) with a backreference (in the RHS):

%s/^\(lorium0{(\[y])}.*\)\<simply\>/\1very/g
    ^^                 ^^           ^^

However, this will only replace the last occurrence of simply on the line.

Related