Note that ripat's awk script will delete all empty lines and all lines that consist entirely of a string of "0" characters.
The following ed script doesn't ignore empty lines and doesn't ignore lines that only contain a string of "0"s. Note that the patterns accepted by awk (which uses extended regular expressions) and ed (which uses basic regular expressions) are slightly different. If that difference doesn't matter to you, you can try this simple ed script:
#!/bin/ksh
FILE=${1:-f}
PATTERN=${2:-PATTERN}
REPLACE=${3:-@@}
ed -s "$FILE" <<-EOF
2,\$g/$PATTERN/.-1s/$/$REPLACE/
1,\$p
Q
EOF
With the file f
containing a few more lines than were in ripat's example:
PATTERN on line1
line two
line to match PATTERN
last line
PATTERN after empty line
000
PATTERN after 000
0
PATTERN after 0
PATTERN after blank line
where the next to the last line just contains a space character, the ed script above produces the output:
PATTERN on line1
line two@@
line to match PATTERN
last line
@@
PATTERN after empty line
000@@
PATTERN after 000
0@@
PATTERN after 0
@@
PATTERN after blank line
while ripat's awk script produces the output:
PATTERN on line1
line two@@
line to match PATTERN
last line
PATTERN after empty line
PATTERN after 000
PATTERN after 0
@@
PATTERN after blank line
If your pattern or the string to be added to lines before those matching the pattern contain any slash ( /
) characters, replace the slashes in the ed g and s commands with a character (other than a newline character) that will never appear in your pattern or added text. I frequently use a control-G for this when processing files that don't contain any ASCII BEL (sometimes called alert) characters (it shows up nicely when I'm editing the script with vi, but it is sometimes hard to describe in text to naive users).
If the difference between BREs and EREs matters, the following awk script will produce the same output as the ed script above. With any of these scripts, if the regular expression contains any meta-characters used in the type of RE you're using, they will have to be escaped appropriately. If you're using ed, you also have to consider what can happen with ampersand ( &
) and backslash digit ( \x
1 <= x <= 9) in the replacement string. With both ed and awk, special attention will also be required if the pattern and replacement strings contain any dollar signs ( $
).
#!/bin/ksh
FILE=${1:-f}
PATTERN=${2:-PATTERN}
REPLACE=${3:-@@}
awk -v pat="$PATTERN" -v rep="$REPLACE" '
FNR>1 { if($0 ~ pat) print last rep
else print last
}
{ last = $0 }
END { print last }' "$FILE"
As always when writing new awk scripts, if you are using a Solaris/SunOS system, use /usr/xpg4/bin/awk
, /usr/xpg6/bin/awk
, or nawk
instead of /bin/awk
or /usr/bin/awk
.
Note that although I used the Korn shell to test these scripts, any POSIX conforming shell will work. If you don't need the script to provide default values for the file to be processed, the pattern to use, and the string to be added to the lines prior to the lines containing the pattern, you can easily hard wire those values into either of the above scripts and use any shell you want.
Hope this helps...