You could run sed
without -i
and step through output with less
grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less
Then run sed
with -i.bak
to create backups which you can diff afterwards
grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct
Edit: As suggested in comment, use grep --null | xargs -0
. This causes filenames to be terminated by the null-byte, which makes it safe for filenames with unusual characters like newline. Yes, \n
is a valid character in a unix filename. The only forbidden characters are slash /
and the nul character \0
Here are two commands. If you want a command that trims up to the last .*{$
line in a sequence (as @don_crissti does with ed
) you can do:
sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'
...which works by appending every line to H
old space following a \n
ewline character, overwriting h
old space for every line that matches {$
, and swapping ing h
old and pattern spaces for every line that matches ^}
- and thereby flushing its buffer.
It only prints lines which match a {
then a \n
ewline and then PATTERN
at some point - and that only ever happens immediately following a buffer swap.
It elides any lines in a series of {$
matches to the last in the sequence, but you can get all of those inclusive like:
sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'
What it does is swap pattern and h
old spaces for every ...{$.*^}.*
sequence, appends all lines within the sequence to H
old space following a \n
ewline character, and D
eletes up to the first occurring \n
ewline character in pattern space for every line cycle before starting again with what remains.
Of course, the only time it ever gets \n
ewline in pattern space is when an input line matches ^}
- the end of your range - and so when it reruns the script on any other occasion it just pulls in the next input line per usual.
When PATTERN
is found in the same pattern space as a \n
ewline, though, it prints the lot before overwriting it with ^}
again (so it can end the range and flush the buffer).
Given this input file (thanks don):
sometext1{
string1
}
sometext2{
PATTERN
string3
}
sometext3{
string4
string5
string6
}
Header{
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}
The first prints:
sometext2{
PATTERN
string3
}
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
...and the second...
sometext2{
PATTERN
string3
}
Header{
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
Best Answer
If you only need to handle that one line, you could use the sed command
For a slightly more robust approach, the following script will accept arbitrary input and only respond if something matched