vi Editor – Using the Caret Symbol (^) in Substitutions

editorsvi

I'm using CentOS and I was reading about the substitution command, s///, in the vi editor. I wanted to test some of the examples I saw:

:%s/old/new/g     Substitutes old with new throughout the file
:.,$s/old/new/g   Substitutes old with new from the current cursor position to the end of the file

The above examples worked as expected for me, but the following containing the caret symbol (^) didn't work:

 :^,.s/old/new/g   Substitutes old with new from the beginning of the file to the current cursor position

I tried it, but it didn't work, so is caret not working or am I typing the command incorrectly?

Best Answer

In the vi editor, as well as in both ex and ed (as found on BSD systems), the ^ addresses the previous line. This means that the command ^d would delete the previous line, ^m. would swap this line with the previous, and that ^,.s/old/new/g would substitute all strings matching old with new on the previous line and on this line.

The vim editor, being an extended re-implementation of the original vi and ex editors, commonly installed on Linux systems under the names vim, vi, and ex, does not have this way of addressing the previous line, and will respond with "E492: Not an editing command" if you try to use it. You may use - or -1 in its place:

-,.s/old/new/g

Using - or -1 in place of ^ also works in ed, ex and in vi on non-GNU systems.

The POSIX standard says the following about this in relation to the ed editor:

Historically, ed accepted the ^ character as an address, in which case it was identical to the <hyphen-minus> character. POSIX.1-2017 does not require or prohibit this behavior.

There is a similar wording for the vi and ex editors (ex is vi "in line editor mode"):

Historically, ex and vi accepted the ^ character as both an address and as a flag offset for commands. In both cases it was identical to the - character. POSIX.1-2017 does not require or prohibit this behavior.

Note that the text that you seem to be quoting says that ^,. addresses all lines from the top of the file to the current line. This is not correct. It only addresses the previous and the current line, and only does so in "historically accurate" implementations of vi (and ex and ed). To address all lines from the start of the editing buffer to the current line, use 1,..

The ^-instead-of-1 typo could possibly come from thinking that "since $ is the end-of-line anchor in regular expressions, and also the address of the last line in the editing buffer, ^, being the start-of-line anchor in regular expressions, must therefore (by symmetry) be the first line of the editing buffer".

Just to provide another piece of trivia: The ^ address can also not be used in the GNU implementation of the ed editor. As in any other implementation of ed, - or -1 may still be used as an alternative.

Related Question