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