Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Replacing a specfied instance of a pattern in a string

by krisahoch (Deacon)
on Jul 14, 2005 at 21:22 UTC ( [id://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

Replies are listed 'Best First'.
Re: Replacing a specfied instance of a pattern in a string
by ikegami (Patriarch) 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.

      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.

      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.

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 (Sage) 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
Domain Nodelet?
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?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2025-06-21 11:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.