1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
|
.\" $OpenBSD: ae3,v 1.4 2004/04/06 08:19:20 jmc Exp $
.\"
.\" Copyright (C) Caldera International Inc. 2001-2002.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code and documentation must retain the above
.\" copyright notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed or owned by Caldera
.\" International, Inc.
.\" 4. Neither the name of Caldera International, Inc. nor the names of other
.\" contributors may be used to endorse or promote products derived from
.\" this software without specific prior written permission.
.\"
.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
.\" INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" @(#)ae3 8.1 (Berkeley) 6/8/93
.\"
.NH
LINE ADDRESSING IN THE EDITOR
.PP
The next general area we will discuss is that of
line addressing in
.UL ed ,
that is, how you specify what lines are to be
affected by editing commands.
We have already used constructions like
.P1
1,$s/x/y/
.P2
to specify a change on all lines.
And most users are long since familiar with
using a single newline (or return) to print the next line,
and with
.P1
/thing/
.P2
to find a line that contains `thing'.
Less familiar, surprisingly enough, is the
use of
.P1
?thing?
.P2
to scan
.ul
backwards
for the previous occurrence of `thing'.
This is especially handy when you realize that the thing
you want to operate on is back up the page from
where you are currently editing.
.PP
The slash and question mark are the only characters you can
use to delimit a context search, though you can use
essentially any character in a substitute command.
.SH
Address Arithmetic
.PP
The next step is to combine the line numbers
like `\*.', `$', `/.../' and `?...?'
with `+' and `\-'.
Thus
.P1
$-1
.P2
is a command to print the next to last line of
the current file (that is, one line before line `$').
For example, to recall how far you got in a previous editing session,
.P1
$-5,$p
.P2
prints the last six lines.
(Be sure you understand why it's six, not five.)
If there aren't six, of course, you'll get an error message.
.PP
As another example,
.P1
\&\*.-3,\*.+3p
.P2
prints from three lines before where you are now
(at line dot)
to three lines after,
thus giving you a bit of context.
.PP
Another area in which you can save typing effort
in specifying lines is to use `\-' and `+' as line numbers
by themselves.
.P1
-
.P2
by itself is a command to move back up one line in the file.
In fact, you can string several minus signs together to move
back up that many lines:
.P1
---
.P2
moves up three lines, as does `\-3'.
Thus
.P1
-3,+3p
.P2
is also identical to the examples above.
.PP
Since `\-' is shorter than `\*.\-1',
constructions like
.P1
-,\*.s/bad/good/
.P2
are useful. This changes `bad' to `good' on the previous line and
on the current line.
.PP
`+' and `\-' can be used in combination with searches using `/.../' and `?...?',
and with `$'.
The search
.P1
/thing/--
.P2
finds the line containing `thing', and positions you
two lines before it.
.SH
Repeated Searches
.PP
Suppose you ask for the search
.P1
/horrible thing/
.P2
and when the line is printed you discover that it
isn't the horrible thing that you wanted,
so it is necessary to repeat the search again.
You don't have to re-type the search,
for the construction
.P1
//
.P2
is a shorthand for `the previous thing that was searched for',
whatever it was.
This can be repeated as many times as necessary.
You can also go backwards:
.P1
??
.P2
searches for the same thing,
but in the reverse direction.
.PP
Not only can you repeat the search, but you can
use `//' as the left side of a substitute command,
to mean
`the most recent pattern'.
.P1
/horrible thing/
.ft I
.... ed prints line with `horrible thing' ...
.ft R
s//good/p
.P2
To go backwards and change a line, say
.P1
??s//good/
.P2
Of course, you can still use the `&' on the right hand side of a substitute to stand for
whatever got matched:
.P1
//s//&\*(BL&/p
.P2
finds the next occurrence of whatever you searched for last,
replaces it by two copies of itself,
then prints the line just to verify that it worked.
.SH
Default Line Numbers and the Value of Dot
.PP
One of the most effective ways to speed up your editing
is always to know what lines will be affected
by a command if you don't specify the lines it is to act on,
and on what line you will be positioned (i.e., the value of dot) when a command finishes.
If you can edit without specifying unnecessary
line numbers, you can save a lot of typing.
.PP
As the most obvious example, if you issue a search command
like
.P1
/thing/
.P2
you are left pointing at the next line that contains `thing'.
Then no address is required with commands like
.UL s
to make a substitution on that line,
or
.UL p
to print it,
or
.UL l
to list it,
or
.UL d
to delete it,
or
.UL a
to append text after it,
or
.UL c
to change it,
or
.UL i
to insert text before it.
.PP
What happens if there was no `thing'?
Then you are left right where you were _
dot is unchanged.
This is also true if you were sitting
on the only `thing' when you issued the command.
The same rules hold for searches that use
`?...?'; the only difference is the direction
in which you search.
.PP
The delete command
.UL d
leaves dot pointing
at the line that followed the last deleted line.
When line `$' gets deleted,
however,
dot points at the
.ul
new
line `$'.
.PP
The line-changing commands
.UL a ,
.UL c ,
and
.UL i
by default all affect the current line _
if you give no line number with them,
.UL a
appends text after the current line,
.UL c
changes the current line,
and
.UL i
inserts text before the current line.
.PP
.UL a ,
.UL c ,
and
.UL i
behave identically in one respect _
when you stop appending, changing, or inserting,
dot points at the last line entered.
This is exactly what you want for typing and editing on the fly.
For example, you can say
.P1
.ta 1.5i
a
... text ...
... botch ... (minor error)
\&\*.
s/botch/correct/ (fix botched line)
a
... more text ...
.P2
without specifying any line number for the substitute command or for
the second append command.
Or you can say
.P1 2
.ta 1.5i
a
... text ...
... horrible botch ... (major error)
\&\*.
c (replace entire line)
... fixed up line ...
.P2
.PP
You should experiment to determine what happens if you add
.ul
no
lines with
.UL a ,
.UL c ,
or
.UL i .
.PP
The
.UL r
command will read a file into the text being edited,
either at the end if you give no address,
or after the specified line if you do.
In either case, dot points at the last line read in.
Remember that you can even say
.UL 0r
to read a file in at the beginning of the text.
(You can also say
.UL 0a
or
.UL 1i
to start adding text at the beginning.)
.PP
The
.UL w
command writes out the entire file.
If you precede the command by one line number,
that line is written,
while if you precede it by two line numbers,
that range of lines is written.
The
.UL w
command does
.ul
not
change dot:
the current line remains the same,
regardless of what lines are written.
This is true even if you say something like
.P1
/^\*e\*.AB/,/^\*e\*.AE/w abstract
.P2
which involves a context search.
.PP
Since the
.UL w
command is so easy to use,
you should save what you are editing regularly
as you go along
just in case the system crashes, or in case you do something foolish,
like clobbering what you're editing.
.PP
The least intuitive behavior, in a sense, is that of the
.UL s
command.
The rule is simple _
you are left sitting on the last line that got changed.
If there were no changes, then dot is unchanged.
.PP
To illustrate,
suppose that there are three lines in the buffer, and you are sitting on
the middle one:
.P1
x1
x2
x3
.P2
Then the command
.P1
\&-,+s/x/y/p
.P2
prints the third line, which is the last one changed.
But if the three lines had been
.P1
x1
y2
y3
.P2
and the same command had been issued while
dot pointed
at the second line, then the result
would be to change and print only the first line,
and that is where dot would be set.
.SH
Semicolon `;'
.PP
Searches with `/.../' and `?...?' start
at the current line and move
forward or backward respectively
until they either find the pattern or get back to the current line.
Sometimes this is not what is wanted.
Suppose, for example, that the buffer contains lines like this:
.P1
\*.
\*.
\*.
ab
\*.
\*.
\*.
bc
\*.
\*.
.P2
Starting at line 1, one would expect that the command
.P1
/a/,/b/p
.P2
prints all the lines from the `ab' to the `bc' inclusive.
Actually this is not what happens.
.ul
Both
searches
(for `a' and for `b')
start from the same point, and thus they both find the line
that contains `ab'.
The result is to print a single line.
Worse, if there had been a line with a `b' in it
before the `ab' line, then the print command
would be in error, since the second line number
would be less than the first, and it is illegal to
try to print lines in reverse order.
.PP
This is because the comma separator
for line numbers doesn't set dot as each address is processed;
each search starts from the same place.
In
.UL ed ,
the semicolon `;' can be used just like comma,
with the single difference that use of a semicolon
forces dot to be set at that point
as the line numbers are being evaluated.
In effect, the semicolon `moves' dot.
Thus in our example above, the command
.P1
/a/;/b/p
.P2
prints the range of lines from `ab' to `bc',
because after the `a' is found, dot is set to that line,
and then `b' is searched for, starting beyond that line.
.PP
This property is most often useful in a very simple situation.
Suppose you want to find the
.ul
second
occurrence of `thing'.
You could say
.P1
/thing/
//
.P2
but this prints the first occurrence as well as the second,
and is a nuisance when you know very well that it is only
the second one you're interested in.
The solution is to say
.P1
/thing/;//
.P2
This says to find the first occurrence of `thing', set dot to that line, then find the second
and print only that.
.PP
Closely related is searching for the second previous
occurrence of something, as in
.P1
?something?;??
.P2
Printing the third or fourth or ...
in either direction is left as an exercise.
.PP
Finally, bear in mind that if you want to find the first occurrence of
something in a file, starting at an arbitrary place within the file,
it is not sufficient to say
.P1
1;/thing/
.P2
because this fails if `thing' occurs on line 1.
But it is possible to say
.P1
0;/thing/
.P2
(one of the few places where 0 is a legal line number),
for this starts the search at line 1.
.SH
Interrupting the Editor
.PP
As a final note on what dot gets set to,
you should be aware that if you hit the interrupt or delete
or rubout or break key
while
.UL ed
is doing a command, things are put back together again and your state
is restored as much as possible to what it was before the command
began.
Naturally, some changes are irrevocable _
if you are reading or writing a file or making substitutions or deleting lines, these will be stopped
in some clean but unpredictable state in the middle
(which is why it is not usually wise to stop them).
Dot may or may not be changed.
|