aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2022-12-24 13:08:45 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2022-12-24 13:08:45 +0100
commit8eb8874002454c8638e26bd3bca9eaa174c2ef54 (patch)
tree723328ac9c7d15a949dbd01cb5c85f2338e4e14b
parent1b69fbdce80f4ee2d46be63be34b4cfb4e4e11d7 (diff)
downloadsebastiano.tronto.net-8eb8874002454c8638e26bd3bca9eaa174c2ef54.tar.gz
sebastiano.tronto.net-8eb8874002454c8638e26bd3bca9eaa174c2ef54.zip
Added blog post
-rw-r--r--src/blog/2022-12-24-ed/ed.md421
-rw-r--r--src/blog/blog.md1
-rw-r--r--src/blog/feed.xml7
3 files changed, 429 insertions, 0 deletions
diff --git a/src/blog/2022-12-24-ed/ed.md b/src/blog/2022-12-24-ed/ed.md
new file mode 100644
index 0000000..5cd9701
--- /dev/null
+++ b/src/blog/2022-12-24-ed/ed.md
@@ -0,0 +1,421 @@
1# The man page reading club: ed(1)
2
3I enjoyed writing a little introduction at the beginning of every
4post of this series, but I am running out of ideas. I am not much
5of fiction writer. I'll skip this time, maybe I'll get back to doing
6it in the future.
7
8For this episode I chose to explore ed,
9[the standard editor](https://www.gnu.org/fun/jokes/ed-msg.en.html).
10This little piece of software first appeared in the very first
11version of UNIX, in the late '60s. Back then, the most common way
12to interact with a computer was via a
13[teletype](https://en.wikipedia.org/wiki/Teleprinter). This meant
14that, in order to edit a file, you could not simply show a screenful
15of text and modify it interactively.
16
17As we will see in this post, the way you modify your text files
18with ed is by running commands, as you would in your usual
19[shell](../2022-09-13-sh-1). You might wonder why in the world you
20should be interested in using this over a more human-friendly text
21editor. There are at least a couple of reasons:
22
231. You find yourself in a very limited environment (e.g. some ebedded
24 OS) where ed is the only editor available.
252. You want to edit a text file as part of a shell script - you can
26 find an example in my [last blog entry](../2022-11-23-git-host).
27
28## ed(1)
29
30*Follow along at
31[man.openbsd.org](http://man.openbsd.org/OpenBSD-7.2/ed)*
32
33The first section explains a few fundamental things.
34
35First of all, ed can be invoked with a file as an argument. The
36given file is copied into a *buffer*, and changes are written to
37it only when the user issues a `w` command.
38
39ed reads every line the user inputs and tries to interpret it as a
40command. The general form for an ed command is
41
42```
43 [address[,address]]command[parameters]
44```
45
46Where the (optional) addresses specify a range of lines over which
47the command has to operate. See the **Line addressing** section
48below for more info.
49
50Some commands allow you to switch to *input mode*, where ed reads
51text without trying to interpret it as a command - usually for the
52purpose of inserting it in your file - until a line with a single
53dot `.` character is read.
54
55There are only two command line options for ed: `-s` to suppress
56diagnostic messages and `-p prompt` to specify a prompt string for
57its command line.
58
59### Line addressing
60
61Every command operates on one or more lines. The default is the
62*current line*, which is usually set to be the last line affected
63by the last command. For example, after opening a file, the current
64line is set to its last line.
65
66You can specify the line(s) on which a command shall operate by
67prepending one or two *addresses* separated by a comma or a semicolon.
68The difference is the following:
69
70```
71 Each address in a comma-delimited range is interpreted relative to the
72 current address. In a semi-colon-delimited range, the first address is
73 used to set the current address, and the second address is interpreted
74 relative to the first.
75```
76
77For example, let's say you are on line 3. Then the address range
78`5,+4` selects the lines from 5 to 7 (3+4), while `5;+4` selects 5
79to 9 (5+4).
80
81But what is a valid address, actually? Besides simply specifying a
82line number, there are a variety of ways to address line: For
83example, `.` refers to the current line and `$` to the last line
84of the file. As we have seen, you can also specify relative addresses
85in the form `-n` or `+n`. You can also search for a line containing
86a specific patern:
87
88```
89 /re/ The next line containing the regular expression re. The search
90 wraps to the beginning of the buffer and continues down to the
91 current line, if necessary. The second slash can be omitted if
92 it ends a line. "//" repeats the last search.
93```
94
95For more infor about regular expressions, see
96[re_format(7)](http://man.openbsd.org/re_format)
97(or perhaps my next blog entry?). Using question marks instead of
98slashes (like this: `?re?`) searches backwards.
99
100### Commands
101
102ed offers a lot of commands to manipulate text. If you are familiar
103with other UNIX editors such as vi or sed, you may recognize many
104of them.
105
106As usual, they are listed in alphabetic order in the manual page,
107so I took the liberty of re-arranging them into groups. I'll have to
108skip or just briefly mention some of them, otherwise I might just
109as well copy the whole manual page here.
110
111**Address-only commands**
112
113Specifying an address only, without a command, changes the current
114line to the (last) addressed line and it prints it. The default is
115the next line, i.e. if you just press enter ed prints out the next
116line and sets it as the current line.
117
118**Printing lines**
119
120The command `p` prints the addressed line. The command `n` does the
121same, but it also prints line numbers. `l` is the same as `p`, but
122special characters (e.g. new lines) are made visible.
123
124Most commands accept a *print suffix* `p`, `l` or `n` that instructs
125ed to print the last line affected by the command. Thus, the three
126printing commands can be also seen as an *address-only command*
127followed by a print suffix.
128
129**Basic editing**
130
131The commands `a` and `i` toggle *input mode* to let you insert text
132after (**a**ppend) or before (**i**nsert) the last line addressed.
133Usually you want to address a single line, often the current line,
134when using one of these commands.
135
136The commands `d` and `c` can be used to **d**elete or **c**hange
137the addressed lines. The latteris equivalent to `d` followed by an
138`a` command.
139
140**Copying, moving and joining lines.**
141
142The commands `t` and `m` operate on a range and take an extra single
143address (which can be `0`) as a parameter, and copy (**t**ransfer)
144or **m**ove the addressed lines to that location. For example the
145command `2,4t0` will copy the 2nd, 3rd and 4th lines to the beginning
146of the file.
147
148If you want to join multiple lines in one you can use the `j` command.
149
150**Text substitution**
151
152The `s` command is one of the most powerful ed offers, but also one
153of the most complex. It allows you to replace a piece of text, or
154any arbitrary pattern defined by a regular expression, with whatever
155you like.
156
157It comes in three variants:
158
159```
160(.,.)s/pattern/text/
161(.,.)s/pattern/text/g
162(.,.)s/pattern/text/n
163```
164
165Where `pattern` is a regular expression and `text` is simple text.
166The first form replaces only the first occurrence of `pattern` in
167each selected line, while the second replaces every occurrence. In
168the last form, `n` must be a number, and only the n-th occurrence
169is replaced.
170
171There are some special characters that can be used: for example, a
172single `&` in `text` is equivalent to the currently matched text.
173If `text` consists of a single `%`, the `text` argument of the last
174`s` command issued is used.
175
176You may escape any character in `text`, including newlines, by
177prepending a backaslash. To avoid escaping slashes to death, keep
178in mind that you can use any other character, for example a `|`,
179instead of `/` in the `s` command.
180
181Finally, a simple `s` command, without pattern or text, repeats the
182last substitution issued.
183
184Let's put this all together with a single example. We have a file
185that looks like this:
186
187```
188This is the first line
189Another line, called the second line
190/A third line, with boundaries/
191Let's make it four
192```
193
194And run the following ed commands:
195
196```
1971/s/t/T/
1981/s/T/&&/g
1992/s/l/%/
2001,3s
2013s|/|\||g
202```
203
204The result is:
205
206```
207TThis is TThe first lline
208Another llline, called the second line
209|A third lline, with boundaries|
210Let's make it four
211```
212
213Understanding why you get this is left as an exercise for the reader ;-)
214
215**Multiple commands on selected lines**
216
217The commands `g` and `G` are also quite powerful. With
218
219```
220(.,.)g/pattern/command-list
221```
222
223you can specify a list of commands to be executed on every line
224matching the regular expression `pattern`. The commands in the list
225are each on their own line, ended with a backslash. The command `G`
226is essentially an interactive version of `g`. Check the man page
227for more details!
228
229**Marks**
230
231You can mark a line with a single lowercase letter (say x) using
232the command `[address]kx`. What for, you might ask? Well, when
233talking about addresses I omitted to tell you that you can also
234refer to a marked line using `'x`. You only have 26 marks at your
235disposal, and one is only deleted when the line it marks is modified,
236so use them wisely!
237
238**Reading files and commands**
239
240You can use the `r` command to insert the content of a file (with
241`r filename`) or the output of a command (with `r !command`) after
242the current line. This is the same as the `r` command of vi, which
243I have discussed in a [previous blog entry](../2022-09-05-man-col).
244
245**Undo**
246
247Use the `u` command to undo the last command. Using `u` twice
248undoes the undo. No editing history for you, sorry.
249
250**File management**
251
252From inside ed, you can use `e filename` to open a new file (**e**dit),
253`w` to save your changes to the current file (**w**rite) and `q`
254to quit. These commands have an upper-case variant (`E`, `W`, and
255`Q`) that can be used to ignore errors (e.g. quit without saving).
256
257The command `wq` can be used as a shortcut for saving and closing.
258
259### ?
260
261ed is infamously terse with its error messages. Indeed, whatever
262error you make, you are going to be faced with the following
263informative line:
264
265```
266 ?
267```
268
269But don't worry: the command `h` shows a more verbose description
270of the last error. You can use the `H` command to toggle verbose
271error messages for the whole session.
272
273## An example session
274
275Let's write an *Hello world* text file using ed!
276
277Let's start by calling ed with a reasonable prompt, to make our
278life easier.
279
280```
281$ ed -p 'ed > ' hellow.txt
282```
283
284And let's open a (new) file:
285
286```
287ed > e hellow.txt
288```
289
290Don't worry about the (unusually verbose!) error message. The file
291does not exist yet, but it will be created when we save our work
292with `w`. Now let's add a line of text:
293
294```
295ed > a
296Hello, wolrd!
297wq
298
299```
300
301Wait, why is ed still open? And why is it not showing the `ed > `
302prompt? Oh right, we forgot to end the input mode by entering a
303single dot!
304
305```
306.
307ed >
308```
309
310Ok, now we are back in business. But we have to remove the `wq`
311line we entered by mistake:
312
313```
314ed > /wq/d
315```
316
317Let's check that we have written what we intended to by printing
318the content of the file:
319
320```
321ed > 1,$n
3221 Hello, wolrd!
323```
324
325Oh no, there is a typo! No big deal, we can fix it:
326
327```
328ed > 1s/lr/rl/
329```
330
331And now that we are done, we can close our file:
332
333```
334ed > q
335?
336```
337
338Wait, what's going on? Let's check:
339
340```
341ed > h
342warning: file modified
343```
344
345Oh right, we need to save.
346
347```
348ed > wq
349```
350
351And now we are done!
352
353## I/O redirection magic
354
355As all other basic UNIX utilities, ed can be used non-interactively
356by using input / output redirection. As an example, consider the
357interactive session above. The input we fed to ed was:
358
359```
360e hellow.txt
361a
362Hello, wolrd!
363wq
364.
365/wq/d
3661,$n
3671s/lr/rl/
368q
369h
370wq
371```
372
373If we save (a stripped down version of) the text above in a file
374called `edcommands.txt`
375
376```
377a
378Hello, wolrd!
379wq
380.
381/wq/d
3821s/lr/rl/
383wq
384```
385
386and run
387
388```
389$ ed -s hellow2.txt < edcommands.txt
390```
391
392We should obtain a file `hellow2.txt` identical to `hellow.txt`. I
393say "should" because apparently there is a little caveat: when used
394non-interactively, ed exits on the first error it encounters. This
395also happens with the `No such file or directory` error that we get
396at the beginning, if a file `hellow2.txt` does not exist yet. We
397just have to create one in advance, for example with `touch
398hellow2.txt`, and run again the ed command above.
399
400## Conclusions
401
402ed was designed in a time when the computer-human interaction was
403a bit different from now, and it shows. However, its language is
404pleasantly consistent: every action you want to perform is expressed
405in the address-command-parameters form. This makes it easy to learn
406and boring, which is a good thing. Such consistency is much harder
407to achieve in the 2D graphical world - which includes
408[TUIs](https://en.wikipedia.org/wiki/Text-based_user_interface).
409
410At the beginning of the post I have mentioned two use cases for a
411software like ed in the present day: being forced into a limited
412environment and using it in non-interactive mode. But there is at
413least another one: for visually impaired users, modern computer
414interfaces are largely inaccessible, as they can't look at a wall
415of text and pictures to figure out where the stuff they want to
416work on is. On the other hand, an editor like ed does not overwhelm
417users with visual output and does not require them to keep in mind
418more than one line at the time. If you are interest in this topic
419I highly suggest reading the article
420[The command line philosophy](http://www.eklhad.net/philosophy.html)
421by Karl Dahlke, the author of [edbrowse](https://edbrowse.org).
diff --git a/src/blog/blog.md b/src/blog/blog.md
index 3ffa250..514492d 100644
--- a/src/blog/blog.md
+++ b/src/blog/blog.md
@@ -2,6 +2,7 @@
2 2
3[RSS Feed](feed.xml) 3[RSS Feed](feed.xml)
4 4
5* 2022-12-24 [The man page reading club: ed(1)](2022-12-24-ed)
5* 2022-11-23 [Self-hosted git pages with stagit (featuring ed, the standard editor)](2022-11-23-git-host) 6* 2022-11-23 [Self-hosted git pages with stagit (featuring ed, the standard editor)](2022-11-23-git-host)
6* 2022-10-19 [Keeping my email sorted (the hard way)](2022-10-19-email-setup) 7* 2022-10-19 [Keeping my email sorted (the hard way)](2022-10-19-email-setup)
7* 2022-10-01 [The man page reading club: tetris(6)](2022-10-01-tetris) 8* 2022-10-01 [The man page reading club: tetris(6)](2022-10-01-tetris)
diff --git a/src/blog/feed.xml b/src/blog/feed.xml
index 0efe9ec..e84456a 100644
--- a/src/blog/feed.xml
+++ b/src/blog/feed.xml
@@ -9,6 +9,13 @@ Thoughts about software, computers and whatever I feel like sharing
9</description> 9</description>
10 10
11<item> 11<item>
12<title>The man page reading club: ed(1)</title>
13<link>https://sebastiano.tronto.net/blog/2022-12-24-ed</link>
14<description>The man page reading club: ed(1)</description>
15<pubDate>2022-12-24</pubDate>
16</item>
17
18<item>
12<title>Self-hosted git pages with stagit (featuring ed, the standard editor)</title> 19<title>Self-hosted git pages with stagit (featuring ed, the standard editor)</title>
13<link>https://sebastiano.tronto.net/blog/2022-11-23-git-host</link> 20<link>https://sebastiano.tronto.net/blog/2022-11-23-git-host</link>
14<description>Self-hosted git pages with stagit (featuring ed, the standard editor)</description> 21<description>Self-hosted git pages with stagit (featuring ed, the standard editor)</description>

Generated with cgit - Back to sebastiano.tronto.net