Patching multiple files with same text
Larry Wall
lwall at jpl-devvax.JPL.NASA.GOV
Thu Mar 29 11:02:08 AEST 1990
In article <193 at rdb1.UUCP> root at rdb1.UUCP (Robert Barrell) writes:
: In a case where several files may have a given group of text lines, and
: that group of lines must be replaced in all files by another group of lines,
: is there any way to use patch, sed, or awk (sorry, I don't have perl) to perform
: such a patch? The problems I am encountering are:
:
: 1) The original text contains multiple lines, and ALL lines of the original must
: be replaced by the patch.
: 2) The patch is not the same length as the original text.
: 3) The original text is not always in the same relative position within each
: file, so "diff -e" scripts will only work for one file, due to the specific
: line numbers, and context diffs have the same problem because of the actual
: context (which may be different in all files).
: 4) Normal "diff" output, run through "patch" DOES work, but isn't specific
: enough about matching the ENTIRE original text, so if a similar group of
: lines appears in a file which doesn't contain the exact original, or if
: such appears BEFORE the original, a false patch can occur.
:
: I see, in the manuals, that sed has an "N" command for, supposedly, dealing
: with multiple lines, but I haven't quite figured-out how to use it yet (all the
: examples in the manuals are for single lines, and the description of "N" is
: rather terse.
Just construct yourself a fake diff listing that has one hunk containing
all the lines, with no context.
1,3c1,8
< This are
< the old
< lines
---
> And these
> are the new
> lines--
> as many
> as you like,
> but make sure
> the line numbers
> are right.
Then use patch. Depending on the lines, you may be able to generate them
with diff -c0. Or maybe not, if there are common lines.
The shell script to iterate over all the files is left as an exercise.
Or GET perl, and say something like
#!/usr/bin/perl -i.bak
eval 'exec /usr/bin/perl -Si.bak $0 ${$1+"$@"}'
if $running_under_some_shell;
$old = <<'EOF';
This are
the old
lines
EOF
$new = <<'EOF';
And these
are the new
lines--
as many
as you like,
and it
doesn't matter
how many lines you
put here
EOF
$old =~ s/(\W)/\\$1/g; # protect any metacharacters.
undef $/; # treat each file as one line
while (<>) { # for each file
s/$old/$new/; # (add g to do multiple times in each file)
print;
}
This will iterate over all the files you mention on the command line
and edit them in place.
Larry Wall
lwall at jpl-devvax.jpl.nasa.gov
More information about the Comp.unix.questions
mailing list