sed tricks
Writing
a file with the 'w' command
You
may remember that the substitute command can write to a file:
sed -n 's/^[0-9]*[02468] /&/w even' <file
I
used the "&" in the replacement part of the substitution
command so that the line would not be changed. A simpler example is
to use the "w" command, which has the same syntax as the
"w" flag in the substitute command:
sed -n '/^[0-9]*[02468]/ w even' <file
Remember
- only one space must follow the command. Anything else will be considered
part of the file name. The "w" command also has the same
limitation as the "w" flag: only 10 files can be opened
in sed.
Reading
in a file with the 'r' command
There
is also a command for reading files. The command
sed '$r end' <in>out
will
append the file "end" at the end of the file (address "$)."
The following will insert a file after the line with the word "INCLUDE:"
sed '/INCLUDE/ r file' <in >out
You
can use the curly braces to delete the line having the "INCLUDE"
command on it:
#!/bin/sh
sed '/INCLUDE/ {
r file
d
}'
The
order of the delete command "d" and the read file command
"r" is important. Change the order and it will not work.
There are two subtle actions that prevent this from working. The first
is the "r" command writes the file to the output stream.
The file is not inserted into the pattern space, and therefore cannot
be modified by any command. Therefore the delete command does not
affect the data read from the file.
The
earlier example is a crude version of the C preprocessor program.
The file that is included has a predetermined name. It would be nice
if sed allowed a variable (e.g "\1)" instead of a fixed
file name. Alas, sed doesn't have this ability. You could work around
this limitation by creating sed commands on the fly, or by using shell
quotes to pass variables into the sed script. Suppose you wanted to
create a command that would include a file like cpp, but the filename
is an argument to the script. An example of this script is:
% include 'sys/param.h' <file.c >file.c.new
A
shell script to do this would be:
#!/bin/sh
# watch out for a '/' in the parameter
# use alternate search delimiter
sed -e '\_#INCLUDE <'$1'>_{
r '$1'
d
}'