http://www.perlmonks.org?node_id=820332

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

hi... how can i search and replace a match with specific number of times using....
s///;
for eg.. $string="abcabdaaa"; i want to replace "a" by "i"... in $string 'n' times...how can i do that?

"n" is an integer provided by user.

  • Comment on how to search and replace the match with specific number of times in a string
  • Download Code

Replies are listed 'Best First'.
Re: how to search and replace the match with specific number of times in a string
by johngg (Canon) on Jan 29, 2010 at 11:06 UTC

    Simplest would be to use a looping statement modifier.

    $ perl -E ' > $str = q{abcabdaaa}; > say $str; > $str =~ s{a}{i} for 1 .. 3; > say $str;' abcabdaaa ibcibdiaa $

    I hope this is helpful.

    Cheers,

    JohnGG

      Note that doesn't work in the general case. For instance, suppose you want to replace first three sequences of whitespace with a single space.
      s/\s+/ / for 1 .. 3;
      would replace the first sequence three times.
      hi but am facing problem when am replacing by
      $s="***ab***c"; $s=~s{\*}{\*\n} for 1..2; print$s;

      it replaces first * by *\n and the rest it ignores... why can any one explain me pls?

      my output was: * **ab***c
      but desired was
      * * *ab***c
        your code does 2 replaces:
        1. * will be replaced by *\n => so your string is    *\n*ab***c
        2. again, the first * will be replaced by *\n, giving you    *\n\n*ab***c
        If you want to continue your approach, a solution could be:
        1. replace * by some string not containing your search-pattern (e.g. X) $s=~s{\*}{X} for 1..2;
        2. replace the new string by your search-pattern $s=~s{X}{\*\n} for 1..2;

        Or follow some other advice given in this thread...

        HTH, Rata

        I believe you can get the function to work expanding the regex a little bit.

        $s = "***ab***c"; $s =~ s/\*([^\n])/\*\n\1/ for 1 .. 2; print $s;

        Output was:

        * * *ab***c

        Since you know the state it's going to be after it's changed, you can include that in the regex. Hence *, not followed by \n will match, along with the for loop suggested earlier, gives you your count. Using \1 here just puts the next value (after the matched *) back into the string.

        Update: markkawika's comment might be below threshold, so I'll add it here as well, since his regex is better than mine. Suggested regex: s/\*(?!\n)/*\n/

Re: how to search and replace the match with specific number of times in a string
by jwkrahn (Abbot) on Jan 29, 2010 at 12:34 UTC
Re: how to search and replace the match with specific number of times in a string
by JavaFan (Canon) on Jan 29, 2010 at 11:07 UTC
    If replacing doesn't create a new possible match, you could do:
    $string =~ s/a/i/ for 1 .. $N;
    Or, in the rare case searching from the beginning over and over again is expensive, or if a replace could create a new match:
    my $count = 0; $string =~ s/a(??{++ $count <= $N ? "(*ACCEPT)" : "(*FAIL)"})/i/g; # Use '""' instead of '(*ACCEPT)' and '(?!)' instead of '(*FAIL)' on o +ld Perls.

      Note that there is a warning (at least as of the current documentation) that the  (*ACCEPT) backtracking control verb is "... highly experimental [and] is not recommended for production code."

      A slightly different take:

      >perl -wMstrict -le "my $N = 3; my $string = 'XXXXXaXXbXXXc'; $string =~ s{ X (?(?{ $N and $N-- }) | (*FAIL)) }{Xy}xmsg; print $string; " XyXyXyXXaXXbXXXc

      See Special Backtracking Control Verbs in perlre.

Re: how to search and replace the match with specific number of times in a string
by rubasov (Friar) on Jan 29, 2010 at 12:04 UTC
    split has an optional LIMIT argument what you can try to utilize something like this:
    perl -le '$s = "abcabdaaa"; $n = 3; print join( "i", split( /a/, $s, $ +n+1 ))'
    See perldoc -f split for details.
Re: how to search and replace the match with specific number of times in a string (Ignore!)
by BrowserUk (Patriarch) on Jan 30, 2010 at 03:27 UTC

    Ignore!


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.