And also the ed tutorial that is not in [...]
It is in
The Ed Papers. Of course there also is
Ed Mastery.
Much in the above references of this thread. I doubt there is one ultimate document that contains
- unambiguous definitions of all its syntax and semantics
- explains those definitions to mere mortals
- functions as a tutorial for the uninitiated and advanced user alike
For #2 and #3 probably covering the most complete vi/nvi/vim and lookalikes landscape is
Learning the vi and Vim Editors, currently at its
8th edition. Starting using a vi-variant afresh, and appreciating good online (in program and on the www) help and assistance,
vim(1) (
vim.org) might be a choice to consider.
How do you substitute "abc^Jdef" with "abcdef", where ^J is a \n character?
"%s/abc^Jdef/abcdef/" or "%s/abc^Mdef/abcdef/" does not work. Remember that to type a char literally, one types first ^V.
With emacs this is no problem, there one enters a character literally with ^Q before.
Another question:
"%s/abc/ABC/2" should substitute in every line the second occurrence of "abc" with "ABC".
This is still the behaviour of ed
, seems to be half documented in man vi
, but does not work.
Starting with your last question. I'm guessing you're expecting that (n)vi is a strict superset of
ed(1) (specifically with respect to "%s/abc/ABC/2"): it is not. vi originated from ex (
Ex Reference Manual - Version 1.1 − November, 1977), where Bill Joy used ed as a basis:
Ex is a UNIX text editor, based on and largely compatible with the standard UNIX editor ed.
The functionality of
ed(1),
(.,.)s/re/replacement/n
"where n is a positive number, causes only the nth match to be replaced" is just not present in
vi(1), ":%s/abc/ABC/2" does work in vi, but has different semantics. More details later on.
A fine solution with vi working in UNIX collaboration style with sed is:
:%!sed -e 's/abc/ABC/2'
With sed, you can also do
:%!sed -e 's/abc/ABC/2g'
, replacing all matched occurrences (
g
) starting with the second match etc.; thus skipping just the first matched occurrence. This functionality is not available in ed.
A working solution (of sorts) for your "\n" problem in vi, is also utilising sed as an external filter:
:%!sed -ne '1h;2,$H;$g;$s/abc\ndef/abcdef/gp'
This dumps the complete file in the pattern space (treating it as one line) and then uses it for the substitution; to me that feels like a hack. This also defeats the "stream" aspect of sed as a
stream editor.
ed, ex, vi (and variants) and sed are all line-oriented utilities; one more so than the other. I imagine that the historical development context has a lot to do with that. UNIX started its development on a (small) minicomputer (DEC PDP-8) in the sixties; it soon moved to the more workable DEC PDP-11 (still a minicomputer). The PDP-11 was also the basis of ex's initial development by Bill Joy, on a Lear Siegler ADM-3A "glass tube" as video display terminal that had a very constrained keyboard layout. On the other hand, emacs was being developed on a DEC PDP-10: a mainframe computer that was in a completely different category. See for more Bill Joy ed/ex/vi 300 baud development history (mixed with an emacs reference):
Understanding the Origins and the Evolution of Vi & Vim
As FreeBSD tends to strive to be POSIX compatible,
Open Group - POSIX is also a valuable source of information, and probably for most items that are relevant to FreeBSD where you could find "defining" information about its syntax and semantics, as good as it gets:
Taking the POSIX relevant texts for your "%s/abc/ABC/2"; the substitution command of
ed:
Code:
(.,.)s/RE/replacement/flags
[...]
The application shall ensure that the value of flags is zero or more of:
count
Substitute for the countth occurrence only of the RE found on each addressed line.
[...]
The synopsis of the substitute commmand of
ex as used in
vi:
Code:
[2addr] s[ubstitute][/pattern/repl/[options][count][flags]]
Here
flags refer to "One or more of the characters '+', '-', '#', 'p', or 'l' (ell)." (see
Command Descriptions in ex) that has a different semantics compared to
flags of
ed.
What might be considered a "total inclusive counting" of all occurrences is the
g option:
Code:
If options includes the letter 'g' (global), all non-overlapping instances of the pattern in the line shall be replaced.
However, for
count in
Command Descriptions in ex:
A positive decimal number. If count is specified, it shall be equivalent to specifying an additional address to the command, unless otherwise specified by the following command descriptions. The additional address shall be equal to the last address specified to the command (either explicitly or by default) plus count-1.
If this would result in an address greater than the last line of the edit buffer, it shall be corrected to equal the last line of the edit buffer.
Which clarifies the different semantics of ex/vi's
count compared to ed's
count.
:3s/abc/ABC/2
used in vi as an ex command, with (numbered lines) as the following text:
Code:
1 this is line abc, abc, abc and abc
2 def this abc line, abc line and still abc line.
3 this is line abc, abc, abc and abc
4 def this abc line, abc line and still abc line.
affects lines 3 and 4 where in each only the first occurrence of
abc
is replaced.
Where is for example the vi (not ex) command >>
documented?
More precise semantics of vi's command mode ">>" are given at
Shift Right:
Code:
[count] > motion
If the motion command is the > command repeated:
If there are less than count -1 lines after the current line in the edit buffer, it shall be an error.
The text region shall be from the current line, up to and including the next count -1 lines.
Shift any line with characters in the text region specified by the count and motion command
one shiftwidth (see the ex shiftwidth option) away from the start of the line, as described by
the ex > command. The unshifted lines shall be copied into the unnamed buffer in line mode.
Current line: If the motion was from the current cursor position toward the end of
the edit buffer, unchanged. Otherwise, set to the first line in the edit buffer that is
part of the text region specified by the motion command.
[...]