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

hi monks, I need to insert a counter tag for all <xxx> tag.
Input: <xxx>...</xxx> <p>...</p> <xxx>...</xxx><xxx>...</xxx> <p>...</p>
Output: <1><xxx>...</xxx> <p>...</p> <2><xxx>...</xxx><3><xxx>...</xxx> <p>...</p>
my present code inserts only for first occurance of <xxx>.
if(/<xxx>/){ s/(<xxx>)/<$cnt>$1/; ++$cnt; }
pls, help me how to code this.

Replies are listed 'Best First'.
Re: find and replace counter
by msbalaji (Chaplain) on Jan 08, 2008 at 06:38 UTC

    hi try this

    use strict; my $cnt=0; while(<DATA>){ $_ =~s/<xxx>/++$cnt.$&/gie; print $_; } __DATA__ <xxx>...</xxx> <p>...</p> <xxx>...</xxx><xxx>...</xxx> <p>...</p>

    Regards
    Balaji. M

      Global substitution along with 'e' to evaluate the replacement text is the trick although you'd be better off not using $& as it imposes a cost on all regular expessions in the program. See Special variables. And you left out the '<' and '>'.

      Given that <xxx> is a constant string it isn't worth while capturing it. If the tag is to be passed in a function then something like

      my $html = get('http://use.perl.org'); my $tag = '<xxx>'; # or '<' . shift . '>' or ... my $count = 0; $html =~ s/$tag/ '<' . ++$count . ">$tag" /ge;

      The reference to LWP::Simple was inspired by this blog on Beautiful Code

      Thanks Balaji, that solves my problem
Re: find and replace counter
by poolpi (Hermit) on Jan 08, 2008 at 09:24 UTC
    Another way to do it ;)

    #!/usr/bin/perl use strict; use warnings; local $/; local $_ = <DATA>; my $c; s/(<xxx>)(?{++$c;})/<$c>$1/g; print; __DATA__ <xxx>fo</xxx> <p>ba</p> <xxx>foo</xxx><xxx>bar</xxx> <p>foobar</p>
    Output:
    <1><xxx>fo</xxx> <p>ba</p> <2><xxx>foo</xxx><3><xxx>bar</xxx> <p>foobar</p>

    HTH,
    PooLpi