15

When I want to replace the two lines

%argdel edit wezterm.lua 

with these:

0argadd wezterm.lua last 

The only regex that seems to work is this:

%s/\V%argdel\nedit \(wezterm.lua\)/0argadd \1\rlast/g 

Notice how in the search part I'm using \n to search for newlines, while when replacing I can't use \n but I need to use \r to force a line break. Why is that? Did I configure something wrong or is this default behavior?

3 Answers 3

15

The documentation is sadly a bit circular about this, but it all comes down to the somewhat dubious choice of internally using NLs to represent NULs, as per :help NL-used-for-Nul, which more or less explains why :help s/\n doesn't do what it intuitively should: \n ultimately becomes a NUL.

It is weird but it is unlikely to ever change so that's the kind of thing we internalize and move on:

Search with \n, replace with \r.

8

I want to give the (correct) answer by Maxim Kim a bit more context.

The root of the misunderstanding lies in how the :substitute command interprets its arguments. In :help :substitute, we see (omission mine):

:[range]s[ubstitute]/{pattern}/{string}/[flags] [count] [ two lines omitted for clarity ] For the {pattern} see pattern. {string} can be a literal string, or something special; see sub-replace-special. 

We see that we have two arguments, separated by / (or whatever separator you choose) and their types are pattern and string, respectively. In a strongly typed language, we would have a signature like substitute(RegEx, String) which would make the difference obvious.

Now that we've established that pattern and string are different types, we have no inclination to believe they would behave the same. To the contrary, the fact that so many escape sequences do behave the same tends to confuse users.

Or, to answer the original question:

Why is that?

Because pattern != string.


When we follow the hotlinks in :help :substitute to :help pattern and :help sub-replace-special, we eventually arrive at the sections quoted in Maxim's answer.

Below :help pattern.txt, we find :help /\n:

\n matches an end-of-line 

And below :help change.txt, we find:

<CR> split line in two at this point (Type the <CR> as CTRL-V <Enter>) \r idem \<CR> insert a carriage-return (CTRL-M) (Type the <CR> as CTRL-V <Enter>) \n insert a <NL> (<NUL> in the file) (does NOT break the line) 

If nothing else, we learn that we could also use <C-V><CR> (shows up as ^M) in the replacement string. I'd stick with \r, YMMV.

5

Notice how in the search part I'm using \n to search for newlines, while when replacing I can't use \n but I need to use \r to force a line break. Why is that? Did I configure something wrong or is this default behavior?

  • :h /\n says it is used to match end of line in the search pattern
  • :h s/\n says it is not used to break the line in a substitute
  • :h s/\r says it is idem which I think means it is related to the line above, <CR>, which breaks the line in a substitute.

Thus you didn't configure anything wrong, this is default behavior.

1
  • 2
    « Idem » like « ditto » (« the same ») Commented Oct 20 at 17:43

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.