Like ''sed'', ''ed'' is a line editor. However, if you try to change file contents with ''sed'', and the file is open elsewhere and read by some process, you will find out that GNU ''sed'' and its ''-i'' option will not allow you to edit the file. There are circumstances where you may need that, e.g. editing active and open files, the lack of GNU, or other ''sed'', with "in-place" option available.
Why ''ed''?
* maybe your ''sed'' doesn't support in-place edit
* maybe you need to be as portable as possible
* maybe you need to really edit in-file (and not create a new file like GNU ''sed'')
* last but not least: standard ''ed'' has very good editing and addressing possibilities, compared to standard ''sed''
Don't get me wrong, this is **not** meant as anti-''sed'' article! It's just meant to show you another way to do the job.
===== Commanding ed =====
Since ''ed'' is an interactive text editor, it reads and executes commands that come from ''stdin''. There are several ways to feed our commands to ed:
To inject the needed newlines, etc. it may be easier to use the builtin command, ''printf'' ("help printf"). Shown here as an example Bash function to prefix text to file content:
Since ''ed'' wants commands separated by newlines, I'll use a special Bash quoting method, the C-like strings ''<nowiki>$'TEXT'</nowiki>'', as it can interpret a set of various escape sequences and special characters. I'll use the ''-s'' option to make it less verbose.
Similar to ''vi'' or ''vim'', ''ed'' has a "command mode" and an "interactive mode". For non-interactive use, the command mode is the usual choice.
Commands to ''ed'' have a simple and regular structure: zero, one, or two addresses followed by a single-character command, possibly followed by parameters to that command. These addresses specify one or more lines in the text buffer. Every command that requires addresses has default addresses, so the addresses can often be omitted.
The line addressing is relative to the //current line//. If the edit buffer is not empty, the initial value for the //current line// shall be the last line in the edit buffer, otherwise zero. Generally, the //current line// is the last line affected by a command. All addresses can only address single lines, not blocks of lines!
Line addresses or commands using //regular expressions// interpret POSIX Basic Regular Expressions (BRE). A null BRE is used to reference the most recently used BRE. Since ''ed'' addressing is only for single lines, no RE can ever match a newline.
===== Debugging your ed scripts =====
By default, ''ed'' is not very talkative and will simply print a "?" when an error occurs. Interactively you can use the ''h'' command to get a short message explaining the last error. You can also turn on a mode that makes ''ed'' automatically print this message with the ''H'' command. It is a good idea to always add this command at the beginning of your ed scripts:
the '','' (comma) in front of the ''p'' command is a shortcut for ''1,$'' which defines an address range for the first to the last line, '',p'' thus means print the whole file, after it has been modified. When your script runs sucessfully, you only have to replace the '',p'' by a ''w''.
Of course, even if the file is not modified by the ''p'' command, **it's always a good idea to have a backup copy!**
===== Editing your files =====
Most of these things can be done with ''sed''. But there are also things that can't be done in ''sed'' or can only be done with very complex code.
==== Simple word substitutions ====
Like ''sed'', ''ed'' also knows the common ''s/FROM/TO/'' command, and it can also take line-addresses. **If no substitution is made on the addressed lines, it's considered an error.**
Compared with two other methods (using ''tr'' or ''sed''), you don't have to delete all newlines and manually add one at the end.
==== File operations ====
=== Insert another file ===
How do you insert another file? As with ''sed'', you use the ''r'' (read) command. That inserts another file at the line before the last line (and prints the result to stdout - '',p''):
Since the default for the ''ed'' "print line number" command is the last line, a simple ''='' (equal sign) will print this line number and thus the number of lines of the file:
* [[http://www.gnu.org/software/ed/manual/ed_manual.html | Gnu ed]] - if we had to guess, you're probably using this one.
* POSIX [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38 | ed]], [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html#tag_20_40 | ex ]], and [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html#tag_20_152 | vi ]]
* [[ http://sdf.lonestar.org/index.cgi?tutorials/ed ]] - ed cheatsheet on sdf.org
Misc info / tutorials:
* [[ http://mywiki.wooledge.org/BashFAQ/021 | How can I replace a string with another string in a variable, a stream, a file, or in all the files in a directory? ]] - BashFAQ