What ed and ex lack in intutitive interface design, they make up for when used in batch editing shell scripts. For example, you might be maintaining a web site with a lot of static content all stored in traditional HTML files. One such file might look like this:
<html> <body> <h1>Hello, world!</h1> <p>Glad you could make it <img src="/graphics/smiley.gif" alt="[:-)]">. <p>Here's a picture of my house: <img src="/graphics/house.gif" alt="[my house]"> </body> </html>
One day, you get an email that all the images will now be served out of the directory /img instead of /graphics. Also, all existing gif files have been replaced with png files. Although these changes don't sound like much, making these modifications to a large number of files quickly becomes tedious. By writing a shell script that calls either ed or ex, you will not only solve today's problem, but you'll also be ready to make new changes to the files whenever that becomes necessary. A Bourne shell script that makes these changes looks like the following:
#!/bin/sh # Convert some of the hard coded values in HTML # into the new site schema # Patterns to be replaced old_graphics_dir="graphics" old_graphics_ext="gif" # new values new_graphics_dir="img" new_graphics_ext="png" # Make the changes for file in *html; do ed $file <<EOF 1,\$s/$old_graphics_dir/$new_graphics_dir/g 1,\$s/$old_graphics_ext/$new_graphics_ext/g w EOF done
The script is fairly simple. It defines a few variables to hold the patterns to be found and replaced. The replacement values are defined next. This script is meant to be run in the directory containing all the HTML files. The list of all files ending in "html" is iterated over in a for loop in which ed is fed commands from a here document. Recall that $ is a special character for Bourne shell and must be escaped in the line-addressing part of the ed command. After the search and replace operations finish, the ed buffers need to be written back to disk with the w command. This script works with both ed and ex.
In older versions of ed, you may find that if the first pattern doesn't match, ed doesn't even try the second pattern. If your version does this, one workaround suggested by Chris Torek is to use the global command g like this:
ed - $i << end g/$old_graphics_dir/s//$new_graphics_dir/g g/$old_graphics_ext/s//$new_graphics_ext/g w end
The addition of the - suppresses the two numbers that ed normally prints.
-- CT and JJ
Copyright © 2003 O'Reilly & Associates. All rights reserved.