Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
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 wandering the Monastery: (8)
As of 2015-07-07 02:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (86 votes), past polls