Basically, what I’m trying to do is search through a rather large PHP file, and replace any block of PHP code that includes the string “search_term” somewhere in it with some other code. I.e.
<?php
//some stuff
?>
<?php
// some more stuff
$str = "search_term";
// yes...
?>
<?php
// last stuff
?>
should become
<?php
//some stuff
?>
HELLO
<?php
// last stuff
?>
What I’ve got so far is
$string =~ s/<\?php(.*?)search_term(.*?)\?>/HELLO/ims;
This correctly matches the closest closing ?>, but begins the match at the very first <?php, instead of the one closest to the string search_term.
What am I doing wrong?
Generally, I don’t like to use non-greedy matching, because it usually leads to problems like this. Perl looks at your file, finds the first
'<?php', then starts looking for the rest of the regexp. It passes over the first'?>'and the second'<?php'because they match.*, then findssearch_termand the next'?>', and it’s done.Non-greedy matching means that you have a regular expression that matches more things than you really want, and it leaves it up to perl to decide which match to return. It’s better to use a regular expression that matches exactly what you want to match. In this case, you can get what you want by using
((?!\?>).)*instead of.*?((?!\?>)is a negative look-ahead assertion)If you expect multiple matches, you might want to use
/isgrather than/is.Alternatively, just split the file into blocks: