Kevin
Kevin

Reputation: 215

How I replace a pattern only once using vim script

I am new in vim scripting, How I replace a pattern only once. I am using the following code.

%s/^\\docume.*/\\docment\[STRING\]

input

\document{A}
\document{B}
\document{C}
\document{D}

Expected output

\document{STRING}
\document{B}
\document{C}
\document{D}

Upvotes: 1

Views: 559

Answers (2)

sidyll
sidyll

Reputation: 59297

The % that you used is the range of lines where the command will be processed, in this case it means from the first line to the last (could also be written as :1,$s/regex/...).

The address specified can be of one line only as well, like:

  • :3s/regex/.../ operate in line 3 only
  • :$s/regex/.../ operate in the last line only

A search can also be used as part of a range: :/search/s/regex/replace/. However, just as the / which we use to search a file, it will start the search after the current cursor position. If you want to match the first occurrence of a file you can create move to line 0 (before line 1) and then do the search. It will find the first occurrence, even in line 1. So the answer to your question is to use a range (even though it will only match a single line in that range).

The final answer isn't :0,/search/ though. The , does not move your cursor, so that will match line 0 to the first search find after cursor position. If you want to move the cursor in your range, use ; instead.

Another little trick: to reuse the search in the range as the search in the substitution, leave the latter empty. This gives a final answer of:

:0;/^\\document\zs.*/s//{STRING}

In other words: do a substitute in the range of line 0 to first match of the pattern, substituting the same pattern by {STRING} (thus operating in one line only, the topmost match of the file).

Please check the manual for range, to know more: :h range

Upvotes: 5

emjay
emjay

Reputation: 440

I don't think there is any decent way to do that. Here's what comes to my mind:

If you don't include % before the substitute command, then vim only replaces the first occurrence in the current line (all occurrences in a line are replaced by adding the /g to the end of the command.

So, you can first search the expression, which gets you to its first occurrence, and then perform the substitution (no %).

I tried this with the execute command (which is like running a vim script), but it didn't work!

:execute "/foo"|"s/foo/bar/"

But running them in two separate execute commands did work.

I guess the search is not working correctly in execute (and, therefore, vim script). If you could find any other way in your script that gets you to the beginning of the line of the first occurrence (which I hope you do) then s/foo/bar would only replace the first one.

Upvotes: 1

Related Questions