@(#)ae6 6.2 (Berkeley) 04/17/91
CUT AND PASTE WITH THE EDITOR
Now we move on to manipulating pieces of files _ individual lines or groups of lines. This is another area where new users seem unsure of themselves.
FilenamesThe first step is to ensure that you know the ed commands for reading and writing files. Of course you can't go very far without knowing r and w . Equally useful, but less well known, is the `edit' command e . Within ed , the command
1 e newfile
2 says `I want to edit a new file called .ul newfile, without leaving the editor.' The e command discards whatever you're currently working on and starts over on .ul newfile. It's exactly the same as if you had quit with the q command, then re-entered ed with a new file name, except that if you have a pattern remembered, then a command like // will still work.
If you enter ed with the command
1 ed file
2 ed remembers the name of the file, and any subsequent e , r or w commands that don't contain a filename will refer to this remembered file. Thus
1 2 ed file1 ... (editing) ... w (writes back in file1) e file2 (edit new file, without leaving editor) ... (editing on file2) ... w (writes back on file2)
2 (and so on) does a series of edits on various files without ever leaving ed and without typing the name of any file more than once. (As an aside, if you examine the sequence of commands here, you can see why many UNIX systems use e as a synonym for ed .)
You can find out the remembered file name at any time with the f command; just type f without a file name. You can also change the name of the remembered file name with f ; a useful sequence is
1 ed precious f junk ... (editing) ...
2 which gets a copy of a precious file, then uses f to guarantee that a careless w command won't clobber the original.
Inserting One File into AnotherSuppose you have a file called `memo', and you want the file called `table' to be inserted just after the reference to Table 1. That is, in `memo' somewhere is a line that says
Table 1 shows that ...and the data contained in `table' has to go there, probably so it will be formatted properly by nroff or troff . Now what?
This one is easy. Edit `memo', find `Table 1', and add the file `table' right there:
1 ed memo /Table 1/ Table 1 shows that ... [response from ed] \*.r table
2 The critical line is the last one. As we said earlier, the r command reads a file; here you asked for it to be read in right after line dot. An r command without any address adds lines at the end, so it is the same as $r .
Writing out Part of a FileThe other side of the coin is writing out part of the document you're editing. For example, maybe you want to copy out into a separate file that table from the previous example, so it can be formatted and tested separately. Suppose that in the file being edited we have
1 \*.TS ...[lots of stuff] \*.TE
2 which is the way a table is set up for the tbl program. To isolate the table in a separate file called `table', first find the start of the table (the `.TS' line), then write out the interesting part:
1 /^\*e\*.TS/ \*.TS [ed prints the line it found] \*.,/^\*e\*.TE/w table
2 and the job is done. If you are confident, you can do it all at once with
1 /^\*e\*.TS/;/^\*e\*.TE/w table
2 and now you have two copies, one in the file you're still editing, one in the file `table' you've just written.
The point is that the w command can write out a group of lines, instead of the whole file. In fact, you can write out a single line if you like; just give one line number instead of two. For example, if you have just typed a horribly complicated line and you know that it (or something like it) is going to be needed later, then save it _ don't re-type it. In the editor, say
1 a ...lots of stuff... ...horrible line... \*. \*.w temp a \*.\*.\*.more stuff\*.\*.\*. \*. \*.r temp a \*.\*.\*.more stuff\*.\*.\*. \*.
2 This last example is worth studying, to be sure you appreciate what's going on.
Moving Lines AroundSuppose you want to move a paragraph from its present position in a paper to the end. How would you do it? As a concrete example, suppose each paragraph in the paper begins with the formatting command `.PP'. Think about it and write down the details before reading on.
The brute force way (not necessarily bad) is to write the paragraph onto a temporary file, delete it from its current position, then read in the temporary file at the end. Assuming that you are sitting on the `.PP' command that begins the paragraph, this is the sequence of commands:
1 \*.,/^\*e\*.PP/-w temp \*.,//-d $r temp
2 That is, from where you are now (`\*.') until one line before the next `\*.PP' (`/^\*e\*.PP/-') write onto `temp'. Then delete the same lines. Finally, read `temp' at the end.
As we said, that's the brute force way. The easier way (often) is to use the .ul move command m that ed provides _ it lets you do the whole set of operations at one crack, without any temporary file.
The m command is like many other ed commands in that it takes up to two line numbers in front that tell what lines are to be affected. It is also .ul followed by a line number that tells where the lines are to go. Thus
1 line1, line2 m line3
2 says to move all the lines between `line1' and `line2' after `line3'. Naturally, any of `line1' etc., can be patterns between slashes, $ signs, or other ways to specify lines.
Suppose again that you're sitting at the first line of the paragraph. Then you can say
1 \*.,/^\*e\*.PP/-m$
2 That's all.
As another example of a frequent operation, you can reverse the order of two adjacent lines by moving the first one to after the second. Suppose that you are positioned at the first. Then
1 m+
2 does it. It says to move line dot to after one line after line dot. If you are positioned on the second line,
1 m--
2 does the interchange.
As you can see, the m command is more succinct and direct than writing, deleting and re-reading. When is brute force better anyway? This is a matter of personal taste _ do what you have most confidence in. The main difficulty with the m command is that if you use patterns to specify both the lines you are moving and the target, you have to take care that you specify them properly, or you may well not move the lines you thought you did. The result of a botched m command can be a ghastly mess. Doing the job a step at a time makes it easier for you to verify at each step that you accomplished what you wanted to. It's also a good idea to issue a w command before doing anything complicated; then if you goof, it's easy to back up to where you were.
Marksed provides a facility for marking a line with a particular name so you can later reference it by name regardless of its actual line number. This can be handy for moving lines, and for keeping track of them even after they've been moved. The .ul mark command is k ; the command
1 kx
2 marks the current line with the name `x'. If a line number precedes the k , that line is marked. (The mark name must be a single lower case letter.) Now you can refer to the marked line with the address
1 \(fmx
2
Marks are most useful for moving things around. Find the first line of the block to be moved, and mark it with .ul \(fma. Then find the last line and mark it with .ul \(fmb. Now position yourself at the place where the stuff is to go and say
1 \(fma,\(fmbm\*.
2
Bear in mind that only one line can have a particular mark name associated with it at any given time.
Copying LinesWe mentioned earlier the idea of saving a line that was hard to type or used often, so as to cut down on typing time. Of course this could be more than one line; then the saving is presumably even greater.
ed provides another command, called t (for `transfer') for making a copy of a group of one or more lines at any point. This is often easier than writing and reading.
The t command is identical to the m command, except that instead of moving lines it simply duplicates them at the place you named. Thus
1 1,$t$
2 duplicates the entire contents that you are editing. A more common use for t is for creating a series of lines that differ only slightly. For example, you can say
1 a .......... x ......... (long line) \*. t\*. (make a copy) s/x/y/ (change it a bit) t\*. (make third copy) s/y/z/ (change it a bit)
2 and so on.
The Temporary Escape `!'Sometimes it is convenient to be able to temporarily escape from the editor to do some other X command, perhaps one of the file copy or move commands discussed in section 5, without leaving the editor. The `escape' command ! provides a way to do this.
If you say
1 !any UNIX command
2 your current editing state is suspended, and the X command you asked for is executed. When the command finishes, ed will signal you by printing another ! ; at that point you can resume editing.
You can really do .ul any X command, including another ed . (This is quite common, in fact.) In this case, you can even do another ! .
On Berkeley X systems, there is an additional (and preferable) mechanism called .ul job control which lets you suspend your edit session (or, for that matter, any program), return to the shell from which you invoked that program, and issue any commands, then resume the program from the point where it was stopped. See .ul An Introduction to the C Shell for more details.