ed: Introduction to line editing

 
 2 Introduction to line editing
 ******************************
 
 'ed' was created, along with the Unix operating system, by Ken Thompson
 and Dennis Ritchie. It is the refinement of its more complex,
 programmable predecessor, 'QED', to which Thompson and Ritchie had
 already added pattern matching capabilities (SeeRegular
 expressions).
 
    For the purposes of this tutorial, a working knowledge of the Unix
 shell 'sh' and the Unix file system is recommended, since 'ed' is
 designed to interact closely with them.  (SeeGNU bash manual
 (bash)Top, for details about bash).
 
    The principal difference between line editors and display editors is
 that display editors provide instant feedback to user commands, whereas
 line editors require sometimes lengthy input before any effects are
 seen. The advantage of instant feedback, of course, is that if a mistake
 is made, it can be corrected immediately, before more damage is done.
 Editing in 'ed' requires more strategy and forethought; but if you are
 up to the task, it can be quite efficient.
 
    Much of the 'ed' command syntax is shared with other Unix utilities.
 
    As with the shell, <RETURN> (the carriage-return key) enters a line
 of input. So when we speak of "entering" a command or some text in
 'ed', <RETURN> is implied at the end of each line. Prior to typing
 <RETURN>, corrections to the line may be made by typing either
 <BACKSPACE> to erase characters backwards, or <CONTROL>-u (i.e., hold
 the CONTROL key and type u) to erase the whole line.
 
    When 'ed' first opens, it expects to be told what to do but doesn't
 prompt us like the shell. So let's begin by telling 'ed' to do so with
 the <P> ("prompt") command:
 
      $ ed
      P
      *
 
    By default, 'ed' uses asterisk ('*') as command prompt to avoid
 confusion with the shell command prompt ('$').
 
    We can run Unix shell ('sh') commands from inside 'ed' by prefixing
 them with <!> (exclamation mark, aka "bang"). For example:
 
      *!date
      Mon Jun 26 10:08:41 PDT 2006
      !
      *!for s in hello world; do echo $s; done
      hello
      world
      !
      *
 
    So far, this is no different from running commands in the Unix shell.
 But let's say we want to edit the output of a command, or save it to a
 file. First we must capture the command output to a temporary location
 called a "buffer" where 'ed' can access it. This is done with 'ed''s
 <r> command (mnemonic: "read"):
 
      *r !cal -m
      137
      *
 
    Here 'ed' is telling us that it has just read 137 characters into
 the editor buffer - i.e., the output of the 'cal' command, which prints
 a simple ASCII calendar. To display the buffer contents we issue the
 <p> ("print") command (not to be confused with the prompt command,
 which is uppercase!). To indicate the range of lines in the buffer that
 should be printed, we prefix the command with <,> (comma) which is
 shorthand for "the whole buffer":
 
      *,p
            June 2006
      Mo Tu We Th Fr Sa Su
                1  2  3  4
       5  6  7  8  9 10 11
      12 13 14 15 16 17 18
      19 20 21 22 23 24 25
      26 27 28 29 30
 
      *
 
    Now let's write the buffer contents to a file named 'junk' with the
 <w> ("write") command:
 
      *w junk
      137
      *
 
    Need we say? It's good practice to frequently write the buffer
 contents, since unwritten changes to the buffer will be lost when we
 exit 'ed'.
 
    The sample sessions below illustrate some basic concepts of line
 editing with 'ed'. We begin by creating a file, 'sonnet', with some
 help from Shakespeare. As with the shell, all input to 'ed' must be
 followed by a <newline> character. Commands beginning with '#' are
 taken as comments and ignored. Input mode lines that begin with '#' are
 just more input.
 
      $ ed
      # The 'a' command is for appending text to the editor buffer.
      a
      No more be grieved at that which thou hast done.
      Roses have thorns, and filvers foutians mud.
      Clouds and eclipses stain both moon and sun,
      And loathsome canker lives in sweetest bud.
      .
      # Entering a single period on a line returns 'ed' to command mode.
      # Now write the buffer to the file 'sonnet' and quit:
      w sonnet
      183
      # 'ed' reports the number of characters written.
      q
      $ ls -l
      total 2
      -rw-rw-r--    1 alm           183 Nov 10 01:16 sonnet
      $
 
    In the next example, some typos are corrected in the file 'sonnet'.
 
      $ ed sonnet
      183
      # Begin by printing the buffer to the terminal with the 'p' command.
      # The ',' means "all lines".
      ,p
      No more be grieved at that which thou hast done.
      Roses have thorns, and filvers foutians mud.
      Clouds and eclipses stain both moon and sun,
      And loathsome canker lives in sweetest bud.
      # Select line 2 for editing.
      2
      Roses have thorns, and filvers foutians mud.
      # Use the substitute command, 's', to replace 'filvers' with 'silver',
      # and print the result.
      s/filvers/silver/p
      Roses have thorns, and silver foutians mud.
      # And correct the spelling of 'fountains'.
      s/utia/untai/p
      Roses have thorns, and silver fountains mud.
      w sonnet
      183
      q
      $
 
    Since 'ed' is line-oriented, we have to tell it which line, or range
 of lines we want to edit. In the above example, we do this by
 specifying the line's number, or sequence in the buffer. Alternatively,
 we could have specified a unique string in the line, e.g., '/filvers/',
 where the '/'s delimit the string in question.  Subsequent commands
 affect only the selected line, a.k.a. the "current" line. Portions of
 that line are then replaced with the substitute command, whose syntax
 is 's/OLD/NEW/'.
 
    Although 'ed' accepts only one command per line, the print command
 'p' is an exception, and may be appended to the end of most commands.
 
    In the next example, a title is added to our sonnet.
 
      $ ed sonnet
      183
      a
       Sonnet #50
      .
      ,p
      No more be grieved at that which thou hast done.
      Roses have thorns, and silver fountains mud.
      Clouds and eclipses stain both moon and sun,
      And loathsome canker lives in sweetest bud.
       Sonnet #50
      # The title got appended to the end; we should have used '0a'
      # to append "before the first line".
      # Move the title to its proper place.
      5m0p
       Sonnet #50
      # The title is now the first line, and the current address has been
      # set to the address of this line as well.
      ,p
       Sonnet #50
      No more be grieved at that which thou hast done.
      Roses have thorns, and silver fountains mud.
      Clouds and eclipses stain both moon and sun,
      And loathsome canker lives in sweetest bud.
      wq sonnet
      195
      $
 
    When 'ed' opens a file, the current address is initially set to the
 address of the last line of that file. Similarly, the move command 'm'
 sets the current address to the address of the last line moved.
 
    Related programs or routines are 'vi (1)', 'sed (1)', 'regex (3)',
 'sh (1)'. Relevant documents are:
 
      Unix User's Manual Supplementary Documents: 12 -- 13
 
      B. W. Kernighan and P. J. Plauger: "Software Tools in Pascal",
      Addison-Wesley, 1981.