Replace while keeping certain "words" in vi/vim

regex, replace, vi, vim

Solution

Using regex, you could do something like `:%s/\$asd\['\([^']*\)'\]/$this->line('\1')/g`

Step by step:

`%s` - substitute on the whole file

`\$asd\['` - match "$asd['". Notice the `$` and `[` need to be escaped since these have special meaning in regex.

`\([^']*\)` - the `\( \)` can be used to select what's called an "atom" so that you can use it in the replacement. The `[^']` means anything that is not a `'`, and `*` means match 0 or more of them.

`'\]` - finishes our match.

`$this->line('\1')` - replaces with what we want, and `\1` replaces with our matched atom from before.

`g` - do this for multiple matches on each line.

Alternative (macro)

Instead of regex you could also use a macro. For example,

qq/\$asd<Enter>ct'$this->line(<Esc>f]r)q

then `@q` as many times as you need. You can also `@@` after you've used `@q` once, or you can `80@q` if you want to use it 80 times.

Alternative (:norm)

In some cases, using `:norm` may be the best option. For example, if you have a short block of code and you're matching a unique character or position. If you know that "$" only appears in "$asd" for a particular block of code you could visually select it and

:norm $T$ct'this->line(<C-v><Esc>f]r)<Enter>

For a discourse on using :norm more effectively, read `:help :norm` and this reddit post.

Problem

For example, if I have `$asd['word_123']` and I wanted to replace it with `$this->line('word_123')`, keeping the 'word_123'. How could I do that? By using this: ``` %s/asd\[\'.*\'\]/this->line('.*')/g ``` I will not be able to keep the wording in between. Please enlighten me.

Original source