Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Replacing a specfied instance of a pattern in a string

by krisahoch (Deacon)
on Jul 14, 2005 at 21:22 UTC ( #475052=perlquestion: print w/ replies, xml ) Need Help??
krisahoch has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

I have an interesting problem where I need to replace a specific instance of a word in a string.

Example String:Fsih my test variable is fsihd or is it gfsih or gfsihd fsih

I may want to replace the third instance of 'fsih' with 'fish', or the fourth, or even the last. How would you do that? I have tried several ways (regexp) but I failed each time.

Thank you in advance

Kristofer

Comment on Replacing a specfied instance of a pattern in a string
Re: Replacing a specfied instance of a pattern in a string
by ikegami (Pope) on Jul 14, 2005 at 21:32 UTC
    my $str = 'Fsih my test variable is fsihd or is it gfsih or gfsih +d fsih'; # 1111 2222 3333 + 4444 my $substr = 'fsih'; my $replace = 'fish'; my $instance = 3; # 3rd print("$str\n"); my $pos = -length($substr); for (;;) { last if !$instance--; $pos = index($str, $substr, $pos + length($substr)); last if $pos < 0; } substr($str, $pos, length($substr), $replace) if $pos >= 0; print("$str\n");

    Update: Fixed off-by-one error.

      Now, is there a way to do it with Regular Expression?
        my $str = 'Fsih my test variable is fsihd or is it gfsih or gfsih +d fsih'; # 1111 2222 3333 + 4444 my $substr = 'fsih'; my $regexp = qr/\Q$substr\E/; my $replace = 'fish'; my $instance = 3; # 3rd print("$str\n"); my $pre_count = $instance - 1; $str =~ s/((?:$regexp.*?){$pre_count})$regexp/$1$replace/; print("$str\n");

        You might have noticed both of these are case sensitive. Both can be made case-insensitive. The non-regexp version is most likely much faster. The regexp version can handle regexps instead of constant strings.

      A tad simpler looping, and case-insensitive:
      my $foo = 'Fsih my test variable is fsihd or is it gfsih or gfsihd f +sih'; my $from = 'fsih'; my $which = 3; my $to = 'FISH'; # makes it easy to see $foo =~ /\Q$from\E/ig for (1..$which); substr($foo, pos($foo) - length($from), length($from), $to) if pos($fo +o); print "Foo = $foo\n";

      Caution: Contents may have been coded under pressure.
        That reminds me of /c!
        my $str = 'Fsih my test variable is fsihd or is it gfsih or gfsih +d fsih'; # 1111 2222 3333 + 4444 my $substr = 'fsih'; my $regexp = qr/\Q$substr\E/; my $replace = 'fish'; my $instance = 3; # 3rd print("$str\n"); scalar $str =~ /\G.*?$regexp/gc while --$instance; $str =~ s/\G(.*?)$regexp/$1$replace/; print("$str\n");

        The /c is needed in case there are less than $instance instances of the search string.

Re: Replacing a specfied instance of a pattern in a string
by Roy Johnson (Monsignor) on Jul 14, 2005 at 21:40 UTC
    One way:
    my $foo = 'Fsih my test variable is fsihd or is it gfsih or gfsihd fsi +h'; # Replace the 3rd $foo =~ s/((?:fsih.*?){2})fsih/$1fish/i or warn "Not found"; print "Foo = $foo\n";

    Caution: Contents may have been coded under pressure.

      or to pass the index in use:

      use warnings; use strict; my $foo = 'Fsih my test variable is fsihd or is it gfsih or gfsihd fsi +h'; my $i = 2; # Replace the 3rd $foo =~ s/((?:fsih.*?){$i})fsih/$1fish/i or warn "Not found"; print "Foo = $foo\n";

      Perl is Huffman encoded by design.
Re: Replacing a specfied instance of a pattern in a string (2 more)
by tye (Cardinal) on Jul 15, 2005 at 05:17 UTC
    my $i= 0; $str =~ s/(...)/ 3 == ++$i ? 'fish' : $1 /ge;
    or
    my $i = 3; 0 while $str =~ /fsih/gi && --$i; substr( $str, $-[0], $+[0]-$-[0], 'fish' ) if ! $i;

    - tye        

Re: Replacing a specfied instance of a pattern in a string
by Jasper (Chaplain) on Jul 15, 2005 at 11:01 UTC
    my $instance = 3; $string = s/fsih/--$instance?$&:'fish'/eg;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://475052]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2014-10-26 01:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (149 votes), past polls