Ed is probably one of the earliest text editors. Conceived in 1969, it gradually evolved in 1970s. Ed inspired (or evolved into) many future editors, like vi and sed (it still lives in your mac terminal - just type ed
).
This article covers basic operations with ed. I don't think you will ever need to use it, but it is nice to learn a bit of history.
Those who do not learn history are doomed to repeat it. - George Santayana
Ok, learning ed has nothing to do with doom and gloom. I just thought it might be fun to insert random, profound quote.
Here is what I will cover:
- Printing
- Moving
- Deleting
- Substituting
- Copying
- Saving
- Scripting
Getting started
First, let's create a file, file.txt
, inside:
this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
this is line 6
this is line 7
To edit this file with ed, do ed file.txt
. You can quit with q
.
Printing
To print a line, use p
. You will see "this is line 7"
outputted. Ed starts at last line by default.
Ed is a line editor, meaning operations are performed (usually) on each line (Vim and VSCode are considered file editors).
- To print line 1, do
1p
. - To print line 3, do
3p
.
Moving
To move, type the address (line number).
- To move to line 1, type
1
. - To move to line 5, type
5
.
Deleting
To delete, use d
. Typing just d
deletes current line. It also accepts an address, so you can tell it which line to delete. For example, to delete line 3, do 3d
.
What I didn't tell you is that address in ed does not have to be a line number, it can also be a pattern.
To delete all lines containing word "line"
, do /line/d
. It will delete first matching /line/
pattern. On our file, it will delete "This is line 1"
.
To apply deletion globally, do g/pattern/d
. To delete all lines containing the word "line", we can do g/line/d
.
Substituting
To substitute a string pattern, the syntax is s/pattern/replacement/flag
. I will explain what g
is in a bit. Let's try it with our file. Doing s/line/ramen/g
gives "This is ramen 7"
.
What does the g
flag mean? g
means global. By global I mean, if there are multiple matches in a line, it will apply our substitution to all matches on that one line.
For example, if we have "line1 line2 line3"
in one line, and we run s/line/goofy/
without g
flag, we get "goofy1 line2 line3"
. Compare that if we do s/line/goofy/g
, we get 'goofy1 goofy2 goofy3".
What if you want to apply our substitution to the entire file? We can use g/pat/s/pattern/replacement/g
syntax.
Wait a second. There are a lot going on here: we have two g
s and two pattern ("pat" and "pattern") syntaxes. What is going on?
- the last
g
, as said before, is global flag for each line. It tells ed to apply substitution to all matches within a line. - the first
g
tells ed to apply it to the entire file. It is a global file indicator. - the first
pat
tells ed to apply the substitution on all lines containing "pat". - the second
pattern
tells ed to perform substitution when it sees "pattern".
Most of the time, we want to apply our substitution only on lines containing that very word ("pat"). Luckily, ed has a shortcut for that:
g/pat/s//new/g
With "pattern" left blank, ed automatically uses "pat" for pattern to be replaced.
Copying
t
is copy in ed. You can copy current line in ed with t address
. If we do t1
, it will copy current line to line 1 (since there is already a text on line 1, it will copy it to the next line).
You can also instruct ed to copy line from address X to address Y, with: addressX t addressY
. If we do 1t5
, ed will copy the content of line 1 to line 5.
Saving
To save, just run w
.
Scripting
You can write a series of script for ed to run. Let's try creating a basic one.
With our file containing:
this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
this is line 6
this is line 7
Let's add another line above "this is line 1"
that says "this is line awesome"
. This is what we want our file to look like:
this is line awesome
this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
this is line 6
this is line 7
To do this, I would need to:
- Copy content of current line (7) to the top
- substitute 7 with "awesome"
- save file
- exit
Create a file called ed-script
(you can name it anything you want). Inside, add:
7t0
s/7/awesome
w
q
There are several ways to run ed with our script. Here are two:
- With pipe:
cat ed-script | ed file.txt
- With stdin:
ed file.txt < ed-script
Run it. It should say "awesome" on the first line. Awesome!
Conclusion
We've learned some basic ed commands. Although you will probably never use ed, it helps you to see how early text editors work. If you are a vim/sed user, you probably notice many command overlaps. This is not a coincidence. By learning one tool, you learn the others because they borrow conventions from one another.
Thanks for reading this far. Hope you learned a good piece of history. Happy coding!
Resources
- A Beginner's Guide to Using ed Editor in Linux
- Batch editing files with ed
- Back to 1969 or Introduction to Ed - old-school text editor
- Dougherty, Dale & Arnold Robbins. "sed & awk". Chapter 2.