How to Edit Files with `ed` ============================ What is `ed` ------------- `ed` is an early text editing tool from the early Unix days. Ken Thompson and Dennis Ritchie developed the tool after developing QED, a text line editing tool from Bell Lab's work on Multics: an Operating System led by MIT and General Electric, which made large computer systems at the time. It's code is still connected to various programming tools: like `sed`, `patch`, and `vi`. Working with `ed` teaches an appreciation of the features of fullpage terminal text editors like `vi`, `emacs`, and `nano`. Understanding `ed` elucidates the value of under utilized features, like doing substitution in `vi`. If you find yourself trying out a historic Unix system, knowing about `ed` can come in handy. I decided to edit a Makefile in a PDP-11 simuation, and that experience prompted me to learn a bit about `ed`. - [ed source](https://salsa.debian.org/debian/ed) - [SIMH: Historic Computer Simulation](http://simh.trailing-edge.com/) The `ed` source code is a great example of C programming for someone who is learning C to examine. `ed` is a complicated piece of programming, but it's function is clear, it's pure C, and you are reading a very influencial piece of software. The minds that created `ed` were some of the early pioneers of To get started ---------------- On Debian, you'll need to install the command to use it: `sudo apt install ed` To read about how to use ed, check out the `info` pages. On Debian, you'll need to install `info`: ``` $ apt install -y info $ info ed ``` `ed` commands are entered preceded by the "address" of the command you are calling. The "address" can be a specifc line number, range of lines, or all of the lines that match a regular expression. The `info` page for `ed` explains the basic commands: - '(.)a': append text to the buffer after the addressed line. - '(.,.)c': changes lines in the buffer, and text is inserted in their place. Combination of a select, delete, and insert. - '(.,.)d': delete the addressed lines from the buffer. - '(.,.)y': yank. Copy the current line buffer. - '(.,.)x' put. Insert the "yanked" text after the adress specified. - '(.,.)p': print. Outputs the content of the adressed line. - 'w': write to the file. Prints bytes printed after success. - 'e FILE': Edits FILE, and sets the filename. - 'E FILE': Edits FILE unconditionally. No warning if you overwrite. The beginning of the file can be jumped to with `^` while the end of the file is accessed at `$`. Open a new file ----------------- To open a new called `testfile`: ``` $ ed testfile ``` Type in `a` and press enter to enter the line buffer. Type in lines of text, pressing return to start a new line. to exit the line buffer, type in `.` on a new line and press return. The `w` command writes the data (21 bytes in this example), and we enter `q` to quit. ``` a Line 1 Line 2 Line 3 . w 21 q ``` Addressing lines ------------------ In `ed`, we prefix our commands with the "address" of the line we wish to apply our command to. We can select a single line, a range of lines, or all the lines. ``` # Select just the third line and print 3p # Select the print 3rd through last line 3,p # Select and print all the text (My favorite!) ,p ``` Edit a line with "c" ----------------------- `ed` is kind of clunky, but you can efficiently work on text documents with a little practice. Let's save some text and practice editing it. ``` $ ed testfile2 a Fizing text with ed. You maywant to learn how to do subztitution. Otherwise, you may need to retype lots. . w 101 q ``` Let's fix "Fizing" the hard way. ``` $ ed testfile2 101 ,p Fizing text with ed You maywant to learn to do subztitution. Otherwise, you may need to retype lots. # Looks like line 1 1p Fizing text with ed # Indeed! now rewrite this line with c! 1c Fixing text with ed. . w 102 q ``` With the command 1c, we tell ed that we want to replace the first line, and we can retype the whole line. However, there's a better way to fix a typo. The substitution command ----------------------------- The substitution command allows you to select and replace text efficiently using "regex": a special syntax for representing patterns in text. At it's least complicated level, regex can be specifying a specific string. The special syntax is how we match things in a less specific way. For example, "Fizing" is regex that would match "Fizing" because it's the exact pattern itself, but I could match the same bit of text with "\.\*zing". If you want to hunt down a pattern throughout an entire text file and replace it with a new string, replacing "OLD" with "NEW": ``` ,s/OLD/NEW/g ``` If you ommit the "g" at the end, than `ed` will only replace the first occurance of the pattern that it finds. In this example, it makes sense to hunt down and fix the word with the literal pattern. Next, let's fix "subztitution" and "maywant": ``` $ ed testfile2 102 ,p Fixing text with ed. You maywant to learn to do subztitution. Otherwise, you may need to retype lots. ,s/subztitution/substitution/ ,p Fixing text with ed. You maywant to learn to do substitution. Otherwise, you may need to retype lots. ,s/maywant/may want/ ,p Fixing text with ed. You may want to learn to do substitution. Otherwise, you may need to retype lots. w 103 q ``` Of course, these are trivial examples. For more information, see examples from `info ed`. When we leverage substitution in `ed` we are basically invoking the fuctionality of `sed`, that lives in `ed`. `sed` is a powerful command can execute the substitution functionality of `ed` from the shell. While `ed` is a neat thing to try out, `vi`, `emacs`, or `nano` are probably what you want to use instead. `sed` is a different story: `sed` allows use to pipe input from all sorts of sources and dynamically edit or filter the output. `ed` may be archaic, but as the system that gave us `sed` and `ex` which is the meat of the visual text editor `vi`: making `ed` awesome in my humble opinion.