Effectively using ed (1)

A tutorial/cheatsheet on using ed (a line-oriented text editor) effectively
, Updated: 6 min read

ed is a “line editor” and not a text editor. It’s a distant ancestor to vi, so some commands are may seem familiar.

These are my notes on basic usage, which should be enough to get you started. You’re probably not going to want to use this to write software, but I’ve used it in the past inside scripts for when file modifications are slightly less trivial than append / delete.

Expressions

These are some basic definitions that’re used in command definitions in the next section.

  • line - select a single line

    • Examples:
      • Simple line selection:
        • 1 - select line 1.
        • $ - select the last line of the file.
      • Basic add/subtract is also supported:
        • $-2 - select two lines above the last line.
        • 1+2 - selects the third line.
        • $- - selects the second to last line file. Equal to $-1.
  • range - this is combined with multiple other commands. Running a range standalone selects the last line. Any two line expressions can be combined here.

    • Examples:
      • 1,5 - selects line 5.
      • 1,$ - selects last line of the file.
      • 1,$- - selects all but the last line of the file
  • regex - matches lines containing a regular expression

    • Examples:
      • g/foo/ - selects lines containing the string “foo”
  • inverted regex - matches lines not containing a regular expression

    • Examples:
      • v/foo/ - selects lines not containing the string “foo”
  • addr - in the below commands, “addr” can mean either:

    • a line
    • a range
    • a regular expression

Commands

For most of these commands, the preceding address is optional, and just uses the current position (which can be set by entering a line / range).

Printing

There are two commands for printing a line / range of lines, n and p. They accept the similar address parameter like most other commands:

  • <addr?> n - prints with line numbers

    • Examples:
      • n - prints current line
      • 5n - selects line 5 and prints it.
      • 1,5n - prints the first 5 lines
      • 1,$n - print entire document
      • g/foo/n - prints lines containing “foo”
      • v/foo/n - prints lines not containing “foo”
  • <addr?> p - prints selected lines

    • Examples:
      • p - prints current line
      • 1,5p - prints the first 5 lines
      • 5p - selects line 5 and prints it.
      • 1,$p - print entire document

Editing

  • <range>? j - joins selected lines

    • Examples:
      • 1,5j - joins the first 5 lines
  • <addr?> d - deletes selected lines

    • Examples:
      • 1,5d - delete the first 5 lines
      • d - delete current line
      • 5d - deletes line 5 and prints it.
      • g/hi/d - delete all lines containing “hi”
  • <line?> a - append after selected line

    • Examples:
      • 10a - add lines after line 10. This enters insert mode, and you must terminate your entry with a new line containing a single ”.”
  • <line?> i - insert before selected line

    • Examples:
      • 10i - add lines before line 10. This enters insert mode, and you must terminate your entry with a new line containing a single ”.”
  • <addr?> m <line> - move section from one part to another. Appends directly after the referenced line.

    • Examples:
      • 4m1 move line 4 to after line 1.
      • 4,5m1 move lines 4-5 to after line 1.
  • <addr?> t <line> - copy section from one part to another. Appends directly after the referenced line.

    • Examples:
      • 4t1 copy line 4 to after line 1.
      • 4,5t1 copy lines 4-5 to after line 1.
  • <addr?> c - replace line(s) with one or more lines.

    • Examples:
      • 1c Replace line one. This enters insert mode, and you must terminate your entry with a new line containing a single ”.”
      • 1,5c This replaces lines 1-5. This enters insert mode, and you must terminate your entry with a new line containing a single ”.”

Search & Replace

  • /regex search

    • Cycles through all matches when pressing enter.
    • The current match may be utilized during each iteration
    • Examples
      • /foo - loop through lines containing the regex match for “foo”
  • <addr?> s/oldstr/newstr - single regex replace

    • Replace first occurrence of “oldstr” with “newstr” in the specified lines
    • Examples
      • 1s/foo/bar - replaces first occurrence of “foo” -> “bar” in line 1.
      • 1,$s/foo/bar - replaces first occurrence of “foo” -> “bar” in the entire file
  • <addr?> s/oldstr/newstr/g - global regex replace

    • Replace all occurrences of “oldstr” with “newstr” in the specified lines
    • Examples:
      • 1s/foo/bar/g - replaces all occurrences of “foo” -> “bar” in line 1.
      • 1,$s/foo/bar/g - replaces all occurrences of “foo” -> “bar” in the entire file

File Management

  • f <filename> - changes current filename

    • Examples:
      • f example.txt - changes editing name to example.txt. Note that this does not change the current file, it just affects the next write.
  • <addr?> r <filename?> - read lines into buffer from file. If addr is not specified, current position is used.

    • Examples:
      • r ./example.txt - loads “example.txt”
      • r !ls -la - loads output of command ls-la
  • <addr?> w <filename?> - write current file contents (replace)

    • uses all the lines if none are specified
    • uses current filename if not specified
  • <addr?> W <filename?> - append current file contents (append)

    • uses all the lines if none are specified
    • uses current filename if not specified
  • q - edit current contents

More info

Example Usage using a here document

This example appends a header to the start of a file. Here, we’re appending after line 0, which is the start of the file. I’ve used this to programatically add information to an entire directory of files, using it in combination with a for loop

ed -s "example_file.c" << EOF
0a
/*
* EXAMPLE FILE HEADER
*
* Potentially include license and copyright info here.
*/
.
w
EOF

Subscribe to my Newsletter

Like this post? Subscribe to get notified for future posts like this.

Change Log

  • 11/24/2020 - Initial Revision
  • 2/25/2024 - Fixing typo in example of line joins
  • 11/4/2024 - Fix typo missing "not" in explanation of inverted regex - Thanks to @kensanata

Found a typo or technical problem? file an issue!