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

Hi,

I am trying to do the following find and replace

input: <it>a</it>+2<it>b</it><inf><it>cd</it></inf> <it>a</it>+2<it>b</it><sup><it>cd</it></sup> output: <it>a</it>+2<it>b<inf>cd</inf></it> <it>a</it>+2<it>b<sup>cd</sup></it>
this line of code works fine and does the job
s!</it><inf><it>(.*?)</it></inf>!<inf>$1</inf></it>!g; s!</it><sup><it>(.*?)</it></sup>!<sup>$1</sup></it>!g;
but i want to make it dynamic so i changed it as follows and this way it is not working
s!</it><(.*?)><it>(.*?)</it></$1>!<$1>$2</$1></it>!g;
please let me know whether i can use $1 in find string and if yes how to use it

Replies are listed 'Best First'.
Re: using $1 as find string
by bmann (Priest) on Dec 29, 2004 at 04:34 UTC
    What you're looking for is called a backreference (see perlre). In the pattern you'll want to use\1 (or \2 or \3...) instead of $1 (or $2 ...). On the RHS keep using $1.

    while (<DATA>){ s!</it><(.*?)><it>(.*?)</it></\1>!<$1>$2</$1></it>!g; # ^ here's the difference print; } __DATA__ <it>a</it>+2<it>b</it><inf><it>cd</it></inf> <it>a</it>+2<it>b</it><sup><it>cd</it></sup>
    output: <it>a</it>+2<it>b<inf>cd</inf></it> <it>a</it>+2<it>b<sup>cd</sup></it>

    Update: fixed pointer to \

Re: using $1 as find string
by gopalr (Priest) on Dec 29, 2004 at 05:16 UTC

    Hi Raj,

    I think u made a mistake in find pattern... i.e. you should have used \1 and not $1.

    But in replace pattern we can use either \1 or $1.

    $input='<it>a</it>+2<it>b</it><inf><it>cd</it></inf> <it>a</it>+2<it>b<sup>cd</sup></it>'; $input=~s!</it><(.*?)><it>(.*?)</it></\1>!<\1>$2</$1></it>!sg; print "\n$input";

    Thanks,

    Gopal.R

      Thank you bmann and gopal for your answers, yea now it works fine

      thanks, raj

Re: using $1 as find string
by nedals (Deacon) on Dec 29, 2004 at 04:03 UTC
    It's a bit messy, but returns what you asked for.
    while (<DATA>) { $_ =~ s!(b)</it>(<.+?>)<it>(cd)</it>(<.+?>)!$1$2$3$4</it>!; print $_; } __DATA__ <it>a</it>+2<it>b</it><inf><it>cd</it></inf> <it>a</it>+2<it>b</it><sup><it>cd</it></sup>
Re: using $1 as find string
by revdiablo (Prior) on Dec 29, 2004 at 19:22 UTC

    This code might work fine for what you're doing, but please keep in mind that regular expressions are not very good at doing these kind of substitutions on nested data. For example, if you try the following:

    $_ = "<it>a</it>+2<it>b</it>" . "<sup><it>cd<sup><it>foo</it></sup></it></sup>\n"; s!</it><(.*?)><it>(.*?)</it></\1>!<$1>$2</$1></it>!g; print;

    You'll see that it does not quite do what you expect. To make something that handles data like this, you would have to build a more complex parser (or use one of the ones available -- HTML::TokeParser, HTML::TreeBuilder, etc).