mt2k has asked for the wisdom of the Perl Monks concerning the following question:

How would I go about changing just a small part of a regex?

Example:

$string = " hello <tag> code goes here </tag> more text ";
How would I go about changing $string so that only the \n's between the <TAG> and </TAG> tags become <BR> tags. Meaning that in the end, $string would hold:
$string = " hello <tag><br>code<br>goes here<br></tag> more text ";
My attempt would be something like:
$string =~ s/<tag>(.*?)<\/tag>/$1 =~ s/\n/<br>/gs;/ieg;
but I know that $1, $2, etc. are read-only.... Help!

Replies are listed 'Best First'.
Re: Editting Part of Regex
by chipmunk (Parson) on Mar 08, 2001 at 19:44 UTC
    You're on the right track... You can copy $1 to another variable in order to do the substitution. Also, you'll need to use different delimiters for the nested substitutions.
    $string =~ s{<tag>(.*?)</tag>} {(my $x = $1) =~ s/\n/<br>/g; "<tag>$x</tag>"}gise;
    By using something other than / as a delimiter for the outer substitution, I avoided having to backslash the literal /s.
Re: Editting Part of Regex
by mirod (Canon) on Mar 08, 2001 at 19:55 UTC

    /e is your friend but don't get too friendly:

    #!/bin/perl -w use strict; my $string="hello <tag> code goes here </tag> "; $string=~ s{(<tag>.*?</tag>)}{replace( $1)}egs; print $string; sub replace { my $text_in_tag= shift; $text_in_tag=~ s{\n}{<br />}g; return $text_in_tag; }

    The e modifier means that the replacement expression is eval-ed instead of being treated as a string. Hence $1 is replaced by replace( $1)

    You can also use the old function-in-a-string trick:

    $string=~ s{(<tag>.*?</tag>)}{@{[replace( $1)]}}gs;
(sacked: substr) Re: Editting Part of Regex
by sacked (Hermit) on Mar 08, 2001 at 22:25 UTC
    Here is another, perhaps less pretty, way to do it:
    substr($string, index($string, '<tag>'), rindex($string, '</tag>')) =~ + s/\n(?!$)/<br>/g;

    Update: I was using the return value of rindex as the length parameter to substr. Oops! Here is a correct, albeit even less pretty, version of the above:
    substr($string, index($string, '<tag>'), rindex($string, '</tag>') - i +ndex($string, '<tag>')) =~ s/\n/<br>/g;
    Yech! It gets rid of the negative look-ahead assertion (since the length is corrected), but it's ugly, and duplicates some function calls. A better version (but uses temp vars) is:
    my $st = index($string, '<tag>'); my $en = rindex($string, '</tag>') - $st; substr($string, $st, $en) =~ s/\n/<br>/g;
    Much better. Though I'm still not sure if it's an improvement over the other suggestions above.

    --sacked