Using sed in a shell here-is document

You can use sed to prompt the user for some parameters and then create a file with those parameters filled in. You could create a file with dummy values placed inside it, and use sed to change those dummy values. A simpler way is to use the "here is" document, which uses part of the shell script as if it were standard input:

#!/bin/sh

echo -n 'what is the value? '

read value

sed 's/XXX/'$value'/' <<EOF

The value is XXX

EOF

Click here to get file: sed_hereis.sed When executed, the script says:

what is the value?

If you type in "123," the next line will be:

The value is 123

I admit this is a contrived example. "Here is" documents can have values evaluated without the use of sed. This example does the same thing:

#!/bin/sh

echo -n 'what is the value? '

read value

cat <<EOF

The value is $value

EOF

However, combining "here is" documents with sed can be useful for some complex cases. Note that

sed 's/XXX/'$value'/' <<EOF

will give a syntax error if the user types a space. Better form would be to use

sed 's/XXX/'"$value"'/' <<EOF

Multiple commands and order of execution

As we explore more of the commands of sed, the commands will become complex, and the actual sequence can be confusing. It's really quite simple. Each line is read in. Each command, in order specified by the user, has a chance to operate on the input line. After the substitutions are made, the next command has a chance to operate on the same line, which may have been modified by earlier commands. If you ever have a question, the best way to learn what will happen is to create a small example. If a complex command doesn't work, make it simpler. If you are having problems getting a complex script working, break it up into two smaller scripts and pipe the two scripts together.

Addresses and Ranges of Text

You have only learned one command, and you can see how powerful sed is. However, all it is doing is a grep and substitute. That is, the substitute command is treating each line by itself, without caring about nearby lines. What would be useful is the ability to restrict the operation to certain lines. Some useful restrictions might be:

· Specifying a line by its number.

· Specifying a range of lines by number.

· All lines containing a pattern.

· All lines from the beginning of a file to a regular expression

· All lines from a regular expression to the end of the file.

· All lines between two regular expressions.

Sed can do all that and more. Every command in sed can be proceeded by an address, range or restriction like the above examples. The restriction or address immediately precedes the command:

restriction command

Restricting to a line number

The simplest restriction is a line number. If you wanted to delete the first number on line 3, just add a "3" before the command:

sed '3 s/[0-9][0-9]*//' <file >new

Patterns

Many UNIX utilities like vi and more use a slash to search for a regular expression. Sed uses the same convention, provided you terminate the expression with a slash. To delete the first number on all lines that start with a "#," use:

sed '/^#/ s/[0-9][0-9]*//'

I placed a space after the "/expression/" so it is easier to read. It isn't necessary, but without it the command is harder to fathom. Sed does provide a few extra options when specifying regular expressions. But I'll discuss those later. If the expression starts with a backslash, the next character is the delimiter. To use a comma instead of a slash, use:

sed '\,^#, s/[0-9][0-9]*//'

The main advantage of this feature is searching for slashes. Suppose you wanted to search for the string "/usr/local/bin" and you wanted to change it for "/common/all/bin." You could use the backslash to escape the slash:

sed '/\/usr\/local\/bin/ s/\/usr\/local/\/common\/all/'

It would be easier to follow if you used an underline instead of a slash as a search. This example uses the underline in both the search command and the substitute command:

sed '\_/usr/local/bin_ s_/usr/local_/common/all_'

This illustrates why sed scripts get the reputation for obscurity. I could be perverse and show you the example that will search for all lines that start with a "g," and change each "g" on that line to an "s:"

sed '/^g/s/g/s/g'

Adding a space and using an underscore after the substitute command makes this much easier to read:

sed '/^g/ s_g_s_g'

Er, I take that back. It's hopeless. There is a lesson here: Use comments liberally in a sed script under SunOS. You may have to remove the comments to run the script under a different operating system, but you now know how to write a sed script to do that very easily! Comments are a Good Thing. You may have understood the script perfectly when you wrote it. But six months from now it could look like modem noise.