SysIII/usr/src/man/docs/ed_tut

.ds :? Editor Tutorial
.de PT
.lt \\n(LLu
.pc %
.nr PN \\n%
.if \\n%-1 .if o .tl '\s9\f2\*(:?\fP''\\n(PN\s0'
.if \\n%-1 .if e .tl '\s9\\n(PN''\f2\*(:?\^\fP\s0'
.lt \\n(.lu
..
.ds . \&\s+2.\s0\&
.de UC
\&\\$3\s-1\\$1\s0\\$2
..
.de UL
.if t \&\\$3\f3\\$1\f1\\$2
.if n \&\\$3\f2\\$1\f1\\$2
..
.de IT
\&\\$3\f2\\$1\fP\\$2
..
.de UI
\f3\\$1\fI\\$2\fR\\$3
..
.de P1
.if n .ls 1
.nf
.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
.if t .ta .3i .6i .9i 1.2i 1.5i 1.8i
.tr -\-
.		use first argument as indent if present
.if \\n(.$ .DS I \\$1
.if !\\n(.$ .DS I 5
.bd 1 2
..
.de P2
.br
.bd 1 2
.DE
.bd 1
.tr --
.if n .ls 2
..
.	2=not last lines; 4= no -xx; 8=no xx-
.tr *\(**
.nr PI .2i
.hy 14
'\".	RP
.TL
A Tutorial Introduction to the U\s-2NIX\s+2 Text Editor
.AU
Brian W. Kernighan
.AI
.MH
.AB
.nr PS 9
.nr VS 11
.PP
Almost all text input on
the
.UX
operating system
is done with
the text-editor
.IT ed .
This memorandum is a tutorial guide
to help beginners get started
with text editing.
.PP
Although it does not cover everything,
it does discuss enough for most users'
day-to-day needs.
This includes
printing, appending, changing, deleting, moving and inserting entire lines of text;
reading and writing files;
context searching and line addressing;
the substitute command;
the global commands;
and the use of special characters for advanced editing.
.AE
.if t .2C
.SH
Introduction
.PP
.ul
Ed
is a ``text editor'', that is, an interactive program
for creating and modifying ``text'',
using directions provided by a user at
a terminal.
The text is often a document
like this one,
or a program
or perhaps data for a program.
.PP
This introduction is meant to simplify learning
.ul
ed.
The recommended way to learn
.ul
ed
is to read this document,
simultaneously using
.ul
ed
to follow the examples,
then to read the description in section I of the
.ul
.UX
.ul
Programmer's Manual,
all the while
experimenting with
.ul
ed.
(Solicitation of advice from experienced users is also useful.)
.PP
Do the exercises!
They cover material not completely discussed
in the actual text.
An appendix summarizes the commands.
.SH
Disclaimer
.PP
This is an introduction and a tutorial.
For this reason, no attempt is made to
cover more than a part of the facilities that
.ul
ed
offers
(although this fraction includes the most useful and frequently used
parts).
When you have mastered the Tutorial,
try
.ul
Advanced Editing on
.ul
.UX .
Also,
there is not enough space to explain basic
.UX
procedures.
We will assume that you know how to log on to
.UX ,
and that you have at least a vague understanding
of what a file is.
For more on that, read
.ul
.UX
.ul
for Beginners.
.PP
You must also know what character to type as the end-of-line
on your particular terminal.
This character is the
.UC RETURN
key on most terminals.
Throughout, we will refer to this character,
whatever it is,
as
.UC RETURN .
.SH
Getting Started
.PP
We'll assume that you have logged in to
your system
and it has just printed the prompt character,
usually either a
.UL $
or a
.UL % .
The
easiest way to get
.ul
ed
is to type
.P1
ed	(followed by a return)
.P2
You are now ready to go \-
.ul
ed
is waiting for you to tell it what to do.
.SH
Creating Text \- the Append command ``a''
.PP
As your first problem, suppose you want to create some text
starting from scratch.
Perhaps you are typing the very first
draft of a paper; clearly it will have to start
somewhere, and undergo modifications later.
This section will show how to get some text in, just to
get started.
Later we'll talk about how to change it.
.PP
When
.ul
ed
is first started, it is rather like working
with a blank piece of paper \- there is no text
or information present.
This must be supplied by the person using
.ul
ed;
it is usually done
by typing in the text, or by reading it into
.ul
ed
from a
file.
We will start by typing in some text, and return shortly to how to
read files.
.PP
First a bit of terminology.
In
.ul
ed
jargon, the text being
worked on is said to be ``kept in a buffer.''
Think of the
buffer as a work space, if you like, or simply as the information
that you are going to be editing.
In effect the buffer is like the
piece of paper, on which we will write things, then change some
of them, and finally file the whole thing away for another day.
.PP
The user tells
.ul
ed
what to do to his text
by typing instructions called ``commands.''
Most
commands consist of a single letter,
which must be typed in lower case.
Each command is typed
on a separate line.
(Sometimes the command is preceded by information
about what line or lines of text are to be affected \-
we will discuss these shortly.)
.ul
Ed
makes no response
to most commands \- there is no prompting
or typing of messages like ``ready''.
(This silence is preferred
by experienced users, but sometimes a hangup for beginners.)
.PP
The first command is
.ul
append,
written as the letter
.P1
a
.P2
all
by itself.
It means ``append (or add) text lines to the buffer,
as I type them in.''
Appending is rather like
writing fresh material on a piece of paper.
.PP
So to enter lines of text into the buffer,
just type an
.UL a
followed by a
.UC RETURN ,
followed by the lines of text you want, like this:
.P1
a
Now is the time
for all good men
to come to the aid of their party.
\*.
.P2
.PP
The only way to stop appending is to type a
line that contains only a period.
The ``\*.'' is used
to tell
.ul
ed
that you have finished appending.
(Even experienced users forget that terminating ``\*.''
sometimes.
If
.ul
ed
seems to be ignoring you,
type an extra line with just ``\*.'' on it.
You may then find you've added some garbage lines
to your text, which you'll have to take out later.)
.PP
After the append command has been done, the buffer will
contain the three lines
.P1
Now is the time
for all good men
to come to the aid of their party.
.P2
The
.UL a '' ``
and ``\*.'' aren't there, because they are
not text.
.PP
To add more text to what you already have,
just issue another
.UL a
command, and continue typing.
.SH
Error Messages \- ``?''
.PP
If at any time you make an error in the commands you type to
.ul
ed,
it will tell you by typing
.P1
?
.P2
This is about as cryptic as it can be,
but with practice, you can usually
figure out how you goofed.
.SH
Writing text out as a file \- the Write command ``w''
.PP
It's likely that you'll want to save your text for later use.
To write out the contents of the buffer onto a file,
use the
.ul
write
command
.P1
w
.P2
followed by the filename you want to write on.
This will copy the buffer's contents
onto the specified file
(destroying any previous information on the file).
To save
the text on a file named
.UL junk ,
for example, type
.P1
w junk
.P2
Leave a space between
.UL w
and the file name.
.ul
Ed
will respond by printing
the number of characters it wrote out.
In this case,
.ul
ed
would respond with
.P1
68
.P2
(Remember that blanks and the return character at the end of each
line are included in the character count.)
Writing a file just makes a copy of the text \- the
buffer's contents are not disturbed, so you can go on adding
lines to it.
This is an important point.
.ul
Ed
at all times works on a copy
of a file, not the file itself.
No change in the contents
of a file takes place until you give a
.UL w
command.
(Writing out the text onto a file from time to time as it is being
created is a good idea, since if the system crashes or if you make some horrible mistake, you will lose
all the text in the buffer but any text that was written onto
a file is relatively safe.)
.SH
Leaving ed \- the Quit command ``q''
.PP
To terminate a session with
.IT ed ,
save the text you're working on
by writing it onto a file using the
.UL w
command,
and then type the command
.P1
q
.P2
which
stands for
.IT quit .
The system will respond with
the prompt character
.UL $ "" (
or
.UL % ).
At
this point your buffer vanishes, with all its text,
which is why you want to write it out before quitting.\(dg
.FS
\(dg Actually,
.IT ed
will print 
.UL ?
if you try to quit without writing.
At that point, write if you want;
if not, another
.UL q
will get you out regardless.
.FE
.SH
Exercise 1:
.PP
Enter
.ul
ed
and
create some text using
.P1
a
\&. . . text . . .
\&\fB.\fR
.P2
Write it out using
.UL w .
Then leave
.ul
ed
with the
.UL q
command, and print the file,
to see that everything worked.
(To print a file, say
.P1
pr filename
.P2
or
.P1
cat filename
.P2
in response to
the prompt character.
Try both.)
.SH
Reading text from a file \- the Edit command ``e''
.PP
A common way to get text into the buffer is to read it
from a file in the file system.
This is what you do to edit text
that you saved with the 
.UL w
command in a previous session.
The
.ul
edit
command
.UL e
fetches the entire contents of a file into the buffer.
So if you had saved the three lines
``Now is the time'', etc.,
with a
.UL w
command in an earlier session,
the 
.ul
ed
command
.P1
e junk
.P2
would fetch the entire contents of the file
.UL junk
into the buffer, and respond
.P1
68
.P2
which is the number of characters in
.UL junk .
.ul
If anything was already in the buffer, it is deleted first.
.PP
If you use the
.UL e
command to read a file into the buffer,
then you need not use a file name after a subsequent
.UL w
command;
.ul
ed
remembers the last file name used in an
.UL e
command,
and
.UL w
will write on this file.
Thus a good way to operate is
.P1
ed
e file
[editing session]
w
q
.P2
This way, you can simply say
.UL w
from time to time,
and be secure in the knowledge that
if you got the file name right at the beginning,
you are writing into the proper file each time.
.PP
You can find out at any time what file name
.ul
ed
is remembering by typing the 
.ul
file
command
.UL f .
In this example,
if you typed
.P1
f
.P2
.ul
ed
would reply
.P1
junk
.P2
.SH
Reading text from a file \- the Read command ``r''
.PP
Sometimes you want to read a file into the buffer
without destroying anything that is already there.
This is done by the
.ul
read
command
.UL r .
The command
.P1
r junk
.P2
will read the file
.UL junk
into the buffer;
it adds it
to the end of whatever is already in the buffer.
So if you do a read after
an edit:
.P1
e junk
r junk
.P2
the buffer will contain
.ul
two
copies of the text (six lines).
.P1
Now is the time
for all good men
to come to the aid of their party.
Now is the time
for all good men
to come to the aid of their party.
.P2
Like the
.UL w
and
.UL e
commands,
.UL r
prints
the
number of characters read in, after the reading operation is complete.
.PP
Generally speaking,
.UL r
is much less used than
.UL e .
.SH
Exercise 2:
.PP
Experiment with the
.UL e
command \-
try reading and printing various files.
You may get an error
.UL ?name ,
where
.UL name
is the name of a file;
this means that the file doesn't exist,
typically because you spelled the file name wrong,
or perhaps that you are not allowed to read or write it.
Try alternately reading and appending to see that they work
similarly.
Verify that
.P1
ed filename
.P2
is exactly equivalent to
.P1
ed
e filename
.P2
What does
.P1
f filename
.P2
do?
.SH
Printing the contents of the buffer \- the Print command ``p''
.PP
To
.ul
print
or list the contents of the buffer (or parts
of it) on the terminal, use the print command
.P1
p
.P2
The way this is done is as follows.
Specify the lines where
you want printing to begin and where you want it to end,
separated by a comma, and
followed by the letter
.UL p .
Thus to print the first two lines of the buffer, for
example, (that is, lines 1 through 2) say
.P1
1,2p	(starting line=1, ending line=2 p)
.P2
.ul
Ed
will respond with
.P1
Now is the time
for all good men
.P2
.PP
Suppose you want to print
.ul
all
the lines in the buffer.
You could use
.UL 1,3p
as above if you knew there were exactly
3 lines in the buffer.
But in general, you don't
know how many there are, so what do you use for the ending
line number?
.ul
Ed
provides a shorthand symbol for ``line number of
last line in buffer'' \- the dollar sign
.UL $ .
Use it this
way:
.P1
1,$p
.P2
This will print
.ul
all
the lines in the buffer (line 1 to last line.)
If you want to stop the printing before it is finished,
push the
.UC DEL
or Delete key;
.ul
ed
will type
.P1
?
.P2
and wait for the next command.
.PP
To print the
.ul
last
line of the buffer, you could use
.P1
$,$p
.P2
but
.ul
ed
lets you abbreviate this to
.P1
$p
.P2
You can print any single line by typing the line
number followed by a
.UL p .
Thus
.P1
1p
.P2
produces the response
.P1
Now is the time
.P2
which is the first line of the buffer.
.PP
In fact,
.ul
ed
lets you abbreviate even further:
you can print any single line by typing
.ul
just
the line number \- no need to type the letter
.UL p .
So if you say
.P1
$
.P2
.ul
ed
will print the last line of the buffer.
.PP
You can also use
.UL $
in combinations like
.P1
$\-1,$p
.P2
which prints the last two lines of the buffer.
This helps when you want to see how far you got in typing.
.SH
Exercise 3:
.PP
As before, create some text using the
.UL a
command and
experiment with the
.UL p
command.
You will find, for example,
that you can't print line 0 or a line beyond
the end of the buffer, and that attempts
to print a buffer in reverse order by saying
.P1
3,1p
.P2
don't work.
.SH
The current line \- ``Dot'' or ``.''
.PP
Suppose your buffer still contains the six lines as above,
that you have just typed
.P1
1,3p
.P2
and
.ul
ed
has printed the three lines for you.
Try typing just
.P1
p	(no line numbers)
.P2
This will print
.P1
to come to the aid of their party.
.P2
which is the third line of the buffer.
In fact it is the last
(most recent) line that you have done anything with.
(You just printed it!)
You can
repeat this
.UL p
command without line numbers, and
it will continue to print line 3.
.PP
The reason is that
.ul
ed
maintains a record of the last line
that you did anything to (in this case, line 3, which you
just printed) so that it can be used instead of an explicit
line number.
This most recent line is referred to by the
shorthand symbol
.P1
\&\*.	(pronounced ``dot'').
.P2
Dot is a line number in the same way that
.UL $
is; it means
exactly ``the current line'', or loosely,
``the line you most recently did something to.''
You
can use it in several ways \- one possibility
is to say
.P1
\&\*.,$p
.P2
This will print all the lines from (including) the current
line to the
end of the buffer.
In our example these are lines 3 through 6.
.PP
Some commands change the value of dot, while others do not.
The
.UL p
command sets dot to the number of the last line printed;
the last command will
set both
\*.
and
.UL $
to 6.
.PP
Dot is most useful when used in combinations like this one:
.P1
\&\*.+1	(or equivalently, \*.+1p)
.P2
This means ``print the next line'' and is a handy way to step
slowly through a buffer.
You can also say
.P1
\&\*.\-1	(or \*.\-1p )
.P2
which means ``print the line
.ul
before
the current line.''
This enables you to go backwards if you wish.
Another useful one is something like
.P1
\&\*.\-3,\*.\-1p
.P2
which prints the previous three lines.
.PP
Don't forget that all of these change the value of dot.
You can find out what dot is at any time by typing
.P1
\&\*.=
.P2
.ul
Ed
will respond by printing the value of dot.
.PP
Let's summarize some things about the
.UL p
command
and dot.
Essentially
.UL p
can be preceded by 0, 1, or 2 line numbers.
If there is no line number given, it prints the ``current line'',
the line that dot refers to.
If there is one line number given
(with or without the letter
.UL p ),
it prints that line (and dot is set there); and if there
are two line numbers, it prints all the lines in that range
(and sets dot to the last line printed.)
If two line numbers are specified
the first can't be bigger than the second (see Exercise 2.)
.PP
Typing a single return will cause printing of the next line \-
it's
equivalent to
.UL .+1p .
Try it.
Try typing
a
.UL \- ;
you will find that
it's equivalent to
.UL .\-1p .
.SH
Deleting lines: the ``d'' command
.PP
Suppose you want to get rid of the three extra lines in the buffer.
This is done by the
.ul
delete
command
.P1
d
.P2
Except that
.UL d
deletes lines instead of printing them,
its action is similar to that of
.UL p .
The lines to be deleted are specified for
.UL d
exactly as they are for
.UL p :
.P1
\fIstarting line, ending line\fP d
.P2
Thus the command
.P1
4,$d
.P2
deletes lines 4 through the end.
There are now three lines left, as you can check by using
.P1
1,$p
.P2
And notice that
.UL $
now is line 3!
Dot
is set to the next line after the last line deleted,
unless the last line deleted is the last line in the buffer.
In that case, dot is set to
.UL $ .
.SH
Exercise 4:
.PP
Experiment with
.UL a ,
.UL e ,
.UL r ,
.UL w ,
.UL p
and
.UL d
until you are sure that you
know what they do, and until you understand how dot,
.UL $ ,
and
line numbers are used.
.PP
If you are adventurous, try using line numbers with
.UL a ,
.UL r
and
.UL w
as well.
You will find that
.UL a
will append lines
.ul
after
the line number that you specify (rather than after dot); that
.UL r
reads
a file in
.ul
after
the line number you specify (not necessarily
at the end of the buffer); and that
.UL w
will write out exactly the lines
you specify, not necessarily the whole buffer.
These variations are sometimes handy.
For instance you can insert a file at the beginning of a buffer
by saying
.P1
0r filename
.P2
and you can enter lines at the beginning of the buffer
by saying
.P1
0a
\&. . . \fItext\fP . . .
\*.
.P2
Notice that
.UL .w
is
.ul
very
different from
.P1
\*.
w
.P2
.SH
Modifying text: the Substitute command ``s''
.PP
We are now ready to try one of the most important
of all commands \- the substitute command
.P1
s
.P2
This is the command
that is used to change individual
words or letters within a line or group of lines.
It is what you use, for example, for correcting spelling
mistakes and typing errors.
.PP
Suppose that by a typing error, line 1 says
.P1
Now is th time
.P2
\- the
.IT e
has been left off
.IT the .
You can use
.UL s
to fix this up as follows:
.P1
1s/th/the/
.P2
This says: ``in line 1, substitute for the characters
.IT th
the characters
.IT the .''
To verify
that it works
.IT ed "" (
will not print
the result automatically) say
.P1
p
.P2
and get
.P1
Now is the time
.P2
which is what you wanted.
Notice that dot must have been set to the line
where the substitution took place, since the
.UL p
command
printed that line.
Dot is always set this way with the
.UL s
command.
.PP
The general way to use the substitute command is
.P1
\fIstarting\(hyline, ending\(hyline\fP s/\fIchange this\fP/\fIto this\fP/
.P2
Whatever string of characters is between the first pair of
slashes is replaced by whatever is between the second pair,
in
.ul
all
the lines between
.ul
starting-line
and
.ul
ending-line.
Only the first occurrence on each line is changed, however.
If you want to change
.ul
every
occurrence, see Exercise 5.
The rules for line numbers are the same as those for
.UL p ,
except that dot is set to the last line changed.
(But there is a trap for the unwary: if no substitution
took place, dot is
.ul
not
changed.
This causes an error
.UL ?
as a warning.)
.PP
Thus you can say
.P1
1,$s/speling/spelling/
.P2
and correct the first spelling mistake
on each line
in the text.
(This is useful for people who are consistent
misspellers!)
.PP
If no line numbers are given, the
.UL s
command assumes we mean
``make the substitution on line dot'', so it changes things only
on the current line.
This leads to the very common sequence
.P1
s/something/something else/p
.P2
which makes some correction on the
current line, and then prints it, to make sure it
worked out right.
If it didn't,
you can try again.
(Notice that there is
a
.UL p
on the same line as the
.UL s
command.
With few exceptions,
.UL p
can follow any command;
no other multi-command lines are legal.)
.PP
It's also legal to say
.P1
s/ . . . //
.P2
which means ``change the first
string of characters to
.IT nothing '', ``
i.e.,
remove them.
This is useful for deleting extra words in a line or removing extra
letters from words.
For instance, if you had
.P1
Nowxx is the time
.P2
you can say
.P1
s/xx//p
.P2
to get
.P1
Now is the time
.P2
Notice that
.UL //
(two adjacent slashes) means ``no characters'', not a blank.
There
.ul
is
a difference!
(See below for another meaning of
.UL // .)
.SH
Exercise 5:
.PP
Experiment with the substitute command.
See what happens if you
substitute for some word on a line with several occurrences of that word.
For example, do this:
.P1
a
the other side of the coin
\*.
s/the/on the/p
.P2
You will get
.P1
on the other side of the coin
.P2
A substitute command changes only the first occurrence of the first string.
You can change all occurrences by adding a
.UL g
(for ``global'')
to the
.UL s
command, like this:
.P1
s/ . . . / . . . /gp
.P2
Try other characters instead of slashes to delimit the two sets
of characters in the
.UL s
command \- anything should work
except blanks or tabs.
.PP
(If you get funny results using any of the characters
.P1
^    \*.    $    [    *    \e    &
.P2
read the section on ``Special Characters''.)
.SH
Context searching \- ``/ . . . /''
.PP
With the substitute command mastered, you can move on to
another highly important idea of
.ul
ed
\- context searching.
.PP
Suppose you have the original three line text in the buffer:
.P1
Now is the time
for all good men
to come to the aid of their party.
.P2
Suppose you want to find the line that contains
.IT their
so
you can change it to
.IT the .
Now with only three lines in the buffer, it's pretty easy
to keep track of what line the word
.IT their
is on.
But if the buffer contained several hundred lines,
and you'd been making changes, deleting and rearranging lines,
and so on, you would no longer really know what this line
number would be.
Context searching is simply a method of specifying the desired line,
regardless of what its number is,
by specifying some context on it.
.PP
The way to say ``search for a line
that contains this particular string of characters''
is to type
.P1
/\fIstring of characters we want to find\fP/
.P2
For example,
the
.ul
ed
command
.P1
/their/
.P2
is a context search which
is sufficient to find the desired line \-
it will locate the next occurrence of
the characters between slashes (``their'').
It also sets dot to that line
and prints the line for verification:
.P1
to come to the aid of their party.
.P2
``Next occurrence'' means that
.ul
ed
starts looking for the string at line
.UL .+1 ,
searches to the end of the buffer,
then continues at line 1 and searches to line dot.
(That is, the search ``wraps around'' from
.UL $
to
1.)
It scans all the lines in the buffer until it either finds the desired line
or gets back to dot again.
If the given string of characters can't be found in any line,
.ul
ed
types the error message
.P1
?
.P2
Otherwise it prints the line it found.
.PP
You can do both the search for the desired line
.ul
and
a
substitution all at once, like this:
.P1
/their/s/their/the/p
.P2
which will yield
.P1
to come to the aid of the party.
.P2
There were three parts to that last command:
context search for the desired line, make the substitution, print the line.
.PP
The expression
.UL /their/
is a context search expression.
In their simplest form,
all context search expressions are like this \-
a string of characters surrounded by slashes.
Context searches are interchangeable with line numbers,
so they can be used by themselves to find and print a desired line,
or as line numbers for some other command, like
.UL s .
They were used both ways in the examples above.
.PP
Suppose the buffer contains the three familiar lines
.P1
Now is the time
for all good men
to come to the aid of their party.
.P2
Then the
.ul
ed
line numbers
.P1
/Now/+1
/good/
/party/\-1
.P2
are all context search expressions, and they all refer
to the same line (line 2).
To make a change in line 2,
you could say
.P1
/Now/+1s/good/bad/
.P2
or
.P1
/good/s/good/bad/
.P2
or
.P1
/party/\-1s/good/bad/
.P2
The choice is dictated only by convenience.
You could print all three lines by, for instance
.P1
/Now/,/party/p
.P2
or
.P1
/Now/,/Now/+2p
.P2
or by any number of similar combinations.
The first one of these might be better if you don't
know how many lines are involved.
(Of course, if there were only three lines in the buffer,
you'd use
.P1
1,$p
.P2
but not if there were several hundred.)
.PP
The basic rule is: a context search expression is
.ul
the same as
a line number, so it can be used wherever a line number is needed.
.SH
Exercise 6:
.PP
Experiment with context searching.
Try a body of text with
several occurrences
of the same string of characters, and scan through it using
the same context search.
.PP
Try using context searches as line numbers for the
substitute, print and delete commands.
(They can also be used
with
.UL r ,
.UL w ,
and
.UL a .)
.PP
Try context searching using
.UL ?text?
instead of
.UL /text/ .
This scans lines in the buffer in reverse order
rather than normal.
This is
sometimes useful if you go too far while looking for some
string of characters \- it's an easy way to back up.
.PP
(If you get funny results with any of the characters
.P1
^    \*.    $    [    *    \e    &
.P2
read the section on ``Special Characters''.)
.PP
.ul
Ed
provides a shorthand for repeating a context search
for the same string.
For example,
the
.ul
ed
line number
.P1
/string/
.P2
will find the next occurrence of
.UL string .
It often happens that this is not the desired line,
so the search must be repeated.
This can be done by typing merely
.P1
//
.P2
This shorthand stands for ``the most recently used
context search expression.''
It can
also be used as the first string of the substitute
command, as in
.P1
/string1/s//string2/
.P2
which will find the next occurrence of
.UL string1
and replace it by
.UL string2 .
This can save a lot of typing.
Similarly
.P1
??
.P2
means ``scan backwards for the same expression.''
.SH
Change and Insert \- ``c'' and ``i''
.PP
This section discusses the
.ul
change
command
.P1
c
.P2
which is used to change
or replace a group of one or more lines,
and the
.ul
insert
command
.P1
i
.P2
which is used for inserting a group of one or more lines.
.PP
``Change'', written as
.P1
c
.P2
is used to replace a number of lines with different lines, which
are typed in at the terminal.
For example,
to change lines
.UL .+1
through
.UL $
to something else, type
.P1
\&.+1,$c
\&. . . \fItype the lines of text you want here\fP . . .
\*.
.P2
The lines you type between the
.UL c
command and
the 
.UL .
will take the place of the original lines between
start line and end line.
This is most useful in replacing a line
or several lines which have errors in them.
.PP
If only one line is specified in the
.UL c
command, then just
that line is replaced.
(You can type in as many replacement lines as you like.)
Notice
the use of
.UL .
to end the
input \- this works just like the
.UL .
in the append command
and must appear by itself on a new line.
If no line number is given, line dot is replaced.
The value of dot is set to the last line you typed in.
.PP
``Insert'' is similar to append \- for instance
.P1
/string/i
\&. . . \fItype the lines to be inserted here\fP . . .
\*.
.P2
will insert the given text
.ul
before
the next line that contains ``string''.
The text between
.UL i
and
.UL .
is
.ul
inserted before
the specified line.
If no line number is specified dot is used.
Dot is set to the last line inserted.
.SH
Exercise 7:
.PP
``Change'' is rather like a combination of
delete followed by insert.
Experiment to verify that
.P1
\fIstart, end\fP d
i
.ul
\&. . . text . . .
\*.
.P2
is almost the same as
.P1
\fIstart, end\fP c
.ul
\&. . . text . . .
\*.
.P2
These are not
.ul
precisely
the same
if line
.UL $
gets deleted.
Check this out.
What is dot?
.PP
Experiment with
.UL a
and
.UL i ,
to see that they are
similar, but not the same.
You will observe that
.P1
\fIline\(hynumber\fP a
\&. . . \fItext\fP . . .
\*.
.P2
appends
.ul
after
the given line, while
.P1
\fIline\(hynumber\fP i
\&. . . \fItext\fP . . .
\*.
.P2
inserts
.ul
before
it.
Observe that if no line number is given,
.UL i
inserts before line dot, while 
.UL a
appends
after line dot.
.SH
Moving text around: the ``m'' command
.PP
The move command 
.UL m
is used for cutting and pasting \-
it lets you move a group of lines
from one place to another in the buffer.
Suppose you want to put the first three lines of the buffer at the end instead.
You could do it by saying:
.P1
1,3w temp
$r temp
1,3d
.P2
(Do you see why?)
but you can do it a lot easier with the 
.UL m
command:
.P1
1,3m$
.P2
The general case is
.P1
\fIstart line, end line\fP m \fIafter this line\fP
.P2
Notice that there is a third line to be specified \-
the place where the moved stuff gets put.
Of course the lines to be moved can be specified
by context searches;
if you had
.P1
First paragraph
\&. . .
end of first paragraph.
Second paragraph
\&. . .
end of second paragraph.
.P2
you could reverse the two paragraphs like this:
.P1
/Second/,/end of second/m/First/\-1
.P2
Notice the
.UL \-1 :
the moved text goes
.ul
after
the line mentioned.
Dot gets set to the last line moved.
.SH
The global commands ``g'' and ``v''
.PP
The
.ul
global
command
.UL g
is used to execute one or more 
.ul
ed
commands on all those lines in the buffer
that match some specified string.
For example
.P1
g/peling/p
.P2
prints all lines that contain
.UL peling .
More usefully,
.P1
g/peling/s//pelling/gp
.P2
makes the substitution everywhere on the line,
then prints each corrected line.
Compare this to
.P1
1,$s/peling/pelling/gp
.P2
which only prints the last line substituted.
Another subtle difference is that
the
.UL g
command
does not give a
.UL ?
if
.UL peling
is not found
where the
.UL s
command will.
.PP
There may be several commands
(including
.UL a ,
.UL c ,
.UL i ,
.UL r ,
.UL w ,
but not
.UL g );
in that case,
every line except the last must end with a backslash
.UL \e :
.P1
g/xxx/\*.-1s/abc/def/\\
\&\*.+2s/ghi/jkl/\\
\&\*.-2,\*.p
.P2
makes changes in the lines before and after each line
that contains
.UL xxx ,
then prints all three lines.
.PP
The
.UL v
command is the same as
.UL g ,
except that the commands are executed on every line
that does
.ul
not
match the string following
.UL v :
.P1
v/ /d
.P2
deletes every line that does not contain a blank.
.SH
Special Characters
.PP
You may have noticed that things just don't work right when you used
some characters like
\*.,
.UL * ,
.UL $ ,
and others in
context searches and the substitute command.
The reason is rather complex, although the cure is simple.
Basically,
.ul
ed
treats these characters as special, with special meanings.
For instance,
.ul
in a context search or the first string of the substitute command only,
\*.
means ``any character,'' not a period, so
.P1
/x\*.y/
.P2
means ``a line with an
.UL x ,
.ul
any character,
and a
.UL y ,''
.ul
not
just ``a line with an
.UL x ,
a period, and a
.UL y .''
A complete list of the special characters
that can cause trouble is the following:
.P1
^    \*.    $    [    *    \e
.P2
.ul
Warning:
The backslash character
.UL \e
is special to
.ul
ed.
For safety's sake, 
avoid it where possible.
If you have to use one of the special characters
in a substitute command,
you can turn off its magic meaning temporarily
by preceding it with the backslash.
Thus
.P1
s/\e\e\e\*.\e*/backslash dot star/
.P2
will change
.UL \e.*
into ``backslash dot star''.
.PP
Here is a hurried synopsis of the other special characters.
First, the circumflex
.UL ^
signifies
the beginning of a line.
Thus
.P1
/^string/
.P2
finds
.UL string
only if it is at the beginning of a line:
it will find
.P1
string
.P2
but not
.P1
the string...
.P2
The dollar-sign
.UL $
is just the opposite of the circumflex;
it means the end of a line:
.P1
/string$/
.P2
will only find an occurrence of
.UL string
that is at the end of some line.
This implies, of course,
that
.P1
/^string$/
.P2
will find only a line that contains just
.UL string ,
and
.P1
/^\*.$/
.P2
finds a line containing exactly one character.
.PP
The character
.UL . ,
as we mentioned above,
matches anything;
.P1
/x\*.y/
.P2
matches any of
.P1
x+y
x-y
x y
x\*.y
.P2
This is useful in conjunction with
.UL * ,
which is a repetition character;
.UL a*
is a shorthand for ``any number of
.UL a 's,''
so 
.UL .*
matches any number of anythings.
This is used like this:
.P1
s/\*.*/stuff/
.P2
which changes an entire line,
or
.P1
s/\*.*,//
.P2
which deletes all characters in the line up to and
including the last comma.
(Since
.UL .*
finds the longest possible match,
this goes up to the last comma.)
.PP
.UL [
is used with
.UL ]
to form ``character classes'';
for example,
.P1
/[0123456789]/
.P2
matches any single digit \-
any one of the characters inside the braces
will cause a match.
This can be abbreviated to
.UL [0\-9] .
.PP
Finally, the
.UL &
is another shorthand character \-
it is used only on the right-hand part of a substitute command
where it means ``whatever was matched on the left-hand side''.
It is used to save typing.
Suppose the current line contained
.P1
Now is the time
.P2
and you wanted to put parentheses around it.
You could just retype the line, but
this is tedious.
Or you could say
.P1
s/^/(/
s/$/)/
.P2
using your knowledge of
.UL ^
and
.UL $ .
But the easiest way uses the
.UL & :
.P1
s/\*.*/(&)/
.P2
This says ``match the whole line, and replace it
by itself surrounded by parentheses.''
The
.UL &
can be used several times in a line;
consider
using
.P1
s/\*.*/&?  &!!/
.P2
to produce
.P1
Now is the time?  Now is the time!!
.P2
.PP
You don't have to match the whole line, of course:
if the buffer contains
.P1
the end of the world
.P2
you could type
.P1
/world/s//& is at hand/
.P2
to produce
.P1
the end of the world is at hand
.P2
Observe this expression carefully,
for it illustrates how to take advantage of
.ul
ed
to save typing.
The string
.UL /world/
found the desired line;
the shorthand
.UL //
found the same
word in the line;
and the
.UL &
saves you from typing it again.
.PP
The
.UL &
is a special character only within
the replacement text of a substitute command,
and has no special meaning elsewhere.
You can turn off the special meaning of
.UL &
by preceding it with a
.UL \e :
.P1
s/ampersand/\e&/
.P2
will convert the word ``ampersand'' into the literal symbol
.UL &
in the current line.
.sp 2
.SH
Summary of Commands and Line Numbers
.PP
The general form of
.ul
ed
commands is the command name,
perhaps preceded by one or two line numbers, and,
in the case of
.UL e ,
.UL r ,
and
.UL w ,
followed by a file name.
Only one command is allowed per line,
but a
.UL p
command may follow any other command
(except for
.UL e ,
.UL r ,
.UL w
and
.UL q ).
.LP
.UL a :
Append, that is, 
add lines to the buffer (at line dot, unless
a different line is specified). Appending continues until
\*.
is typed on a new line.
Dot is set to the last line appended.
.LP
.UL c :
Change the specified lines to the new text which follows.
The new lines are terminated by a
\*.,
as with
.UL a .
If no lines are specified,
replace line dot.
Dot is set to last line changed.
.LP
.UL d :
Delete the lines specified.
If none are specified, delete line dot.
Dot is set to the first undeleted line,
unless
.UL $
is deleted,
in which case dot is set to
.UL $ .
.LP
.UL e :
Edit new file.
Any previous
contents of the buffer are thrown away,
so issue a
.UL w
beforehand.
.LP
.UL f :
Print remembered filename.
If a name follows
.UL f
the remembered name will be set to it.
.LP
.UL g :
The command
.P1
g/\(hy\(hy\(hy/commands
.P2
will execute the commands on those lines that contain
.UL --- ,
which can be any context search expression.
.LP
.UL i :
Insert lines before specified line (or dot)
until a
\*.
is typed on a new line.
Dot is set to last line inserted.
.LP
.UL m :
Move lines specified to after the line
named after
.UL m .
Dot is set to the last line moved.
.LP
.UL p :
Print specified lines.
If none specified, print
line dot.
A single line number is equivalent to
.IT line-number
.UL p .
A single return prints
.UL .+1 ,
the next line.
.LP
.UL q :
Quit
.IT ed .
Wipes out all text in buffer
if you give it twice in a row without first giving a
.UL w
command.
.LP
.UL r :
Read a file into buffer (at end unless specified
elsewhere.) Dot set to last line read.
.LP
.UL s :
The command
.P1
s/string1/string2/
.P2
substitutes the characters
.UL string1
into
.UL string2
in the specified lines.
If no lines are specified, make the substitution in line dot.
Dot is set to last line in which a
substitution took place, which means that if no substitution took place, dot is not changed.
.UL s
changes only the first occurrence of
.UL  string1 
on a line;
to change all of them, type a
.UL g
after the final slash.
.LP
.UL v :
The command
.P1
v/\(hy\(hy\(hy/commands
.P2
executes
.UL commands
on those lines that
.ul
do not
contain
.UL --- .
.LP
.UL w :
Write out buffer onto a file.
Dot is not changed.
.LP
.UL .= :
Print value of dot.
.UL = "" (
by itself prints the value of
.UL $ .)
.LP
.UL ! :
The line
.P1
!command\(hyline
.P2
causes
.UL command-line
to be executed as a
.UX
command.
.LP
.UL /-----/ :
Context search.
Search for next line which contains
this string of characters.
Print it.
Dot is set to the line where string
was found.
Search starts at
.UL .+1 ,
wraps around from
.UL $
to
1,
and continues to dot, if necessary.
.LP
.UL ?-----? :
Context search in reverse direction.
Start search
at
.UL .\-1 ,
scan to 1,
wrap around to
.UL $ .
.sp
.I "May 1979"