sed you can do this without slurping the entire file:
sed -e ':top' -e 's/john paul[[:space:]]*george/pete/g;$b' -e '/john paul[[:space:]]*$/!b' -e 'N;btop' input
This is much lighter on memory usage; it only slurps multiple lines when there is a possibility of a multi-line match starting from the current line. And then it only slurps until either the match is found, or until there is no further possibility of a match.
As a bonus, it's POSIX-compliant. (Perl isn't part of POSIX.) Thanks to mikeserv for pointing this out in the comments.
:top sets a label named
s/john paul[[:space:]]*george/pete/g does the substitution you want for whatever is in the pattern space. (Default is line by line.)
$b skips to the end and prints if the current line is the last line of the file.
/john paul[[:space:]]*$/ will match
john paul at the end of the pattern space followed by any amount of whitespace (but nothing other than whitespace), then
! inverts the pattern. So the effect here is to execute the
b command (skip to the end of the script, thus printing the pattern space, reading the next line from the file, and starting from the top of the script) only if there is no possibility of a multi-line match starting with the current pattern space.
N appends the next line from the file to the pattern space (after appending a newline).
btop branches to the
:top label without clearing out the pattern space.