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

I want to search for nth occurence of a pattern in a line. eg:if i want to search for 3rd occurence of "," in a line how do i do that?

2006-05-17 Retitled by Arunbear
Original title: 'serach nth occurence in a line'

  • Comment on search for nth occurrence of a pattern in a line

Replies are listed 'Best First'.
Re: search for nth occurrence of a pattern in a line
by davido (Cardinal) on May 17, 2006 at 08:13 UTC

    The third occurence of a string can be found by stepping through your substring with index. Since ',' is a simple string, not a pattern, index is ideal.

    On the other hand, if you really do want to search for a particular pattern, here's one way to do it with respect to finding the third comma, using a regexp:

    use strict; use warnings; my $string = "a,bc,d,efg"; if( $string =~ m/(?:,[^,]*){2}(,)/ ) { print $'; }

    Dave

Re: search for nth occurrence of a pattern in a line
by ioannis (Abbot) on May 17, 2006 at 08:56 UTC
    Here is a solution. The basic idea to count the times we of the found pattern as we scan the string from left to right. Although we can compact the code into 2 short lines, it is shown bellow longer and verbose.

    # $n is the nth wanted occurence, as indicated by the question. # $i holds how many times we found the pattern my $str = ',n ,pple , d,y'; my ($n, $i) = 4; $str =~ / , # we are searching for the , pattern (?{ $i++}) # we found it again , increament $i /xgc # retain last occurance on failure for (1..$n); # print position in string print +($n == $i) ? pos($str) - 1 : 'not found';
Re: search for nth occurrence of a pattern in a line
by Praveen (Friar) on May 17, 2006 at 08:58 UTC
    Try This
    $str = "The, Sample, sents, kdsjf, jdfhj"; for (split(/,/, $str,3)) { print ; }
    or
    $cnt =0; while($str =~ /(.*?),/g) { $cnt++; print $&, if($cnt ==3); }
Re: search for nth occurrence of a pattern in a line
by parv (Parson) on May 17, 2006 at 08:31 UTC
    You would start with searching this site via "Super search" for something like "nth character occurrence". Otherwise, following algorithm comes to mind (untested; would be pleased to know of any errors) ...
    keep a counter to count the number of occurrences of the pattern, initially -1 (assuming 0-based indexing) keep a marker to note the position of the pattern run loop from the start of a line to its end check if pattern exists if not, exit out of loop else check if counter is same the nth-place required if yes, exit out of loop else, increment the counter set the marker to the start of the pattern loop the loop from the marker + the length of the pattern + 1 at the end, equivalence of counter & desired nth occurrence will give you the result.
Re: search for nth occurrence of a pattern in a line
by jesuashok (Curate) on May 17, 2006 at 08:11 UTC
Re: search for nth occurrence of a pattern in a line
by GrandFather (Saint) on May 17, 2006 at 10:19 UTC

    Employing a little regex look ahead trickery gives something like this:

    use strict; use warnings; my $pat = 'ono'; my $str = <<STR; ono is the pattern to match. ono is found once in onono STR #123456789012345678901234567890123456789012345678901234 # 1 2 3 4 5 for my $count (1..4) { if ($str =~ /(?:(?:(?!$pat).)*($pat)){$count}/) { print "Match at $-[1] for count = $count\n"; } else { print "No match for count = $count\n"; } }

    Prints:

    Match at 0 for count = 1 Match at 29 for count = 2 Match at 50 for count = 3 No match for count = 4

    Note that at least simple regex matches are fine in the pattern including look ahead and look back matches, but avoid capture groups.


    DWIM is Perl's answer to Gödel
Re: search for nth occurrence of a pattern in a line
by japhy (Canon) on May 17, 2006 at 14:09 UTC
    Sounds like an XY Problem to me. Why are you searching for the third occurrence of a comma in a string? Do you want to get at the fourth field in a comma-separated string? If so, use split().

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: search for nth occurrence of a pattern in a line
by duff (Parson) on May 17, 2006 at 18:26 UTC

    In perl6 it's m:3rd/,/ and .pos will tell you at what position it matched. :-)

Re: search for nth occurrence of a pattern in a line
by TedPride (Priest) on May 17, 2006 at 20:21 UTC
    True, I suppose. How about:
    use strict; use warnings; my ($str, $nth, $find, $p); $str = "dsf,sdg,hjhgj,gjkh"; $nth = 3; $find = ','; $str =~ m/(?:.*?$find){$nth}/g; $p = pos($str) - length($find); print substr($str, $p) if $p > -1;
    That doesn't use either one :)
Re: search for nth occurrence of a pattern in a line
by TedPride (Priest) on May 17, 2006 at 20:06 UTC
    use strict; use warnings; my ($str, $nth, $p); $str = "dsf,sdg,hjhgj,gjkh"; $p = -1; $nth = 3; while ($str =~ /,/g) { $p = pos($str) - length($&), last if !--$nth; } print substr($str, $p) if $p != -1;
    Regex is better imho, since you don't know if you might want to do a pattern match some time in the future.
      pos($str) - length($&)? Ewwww. First of all, $& is a Curse, and second, you can just use $-[0] to get the same location.
      while ($str =~ /,/g) { $p = $-[0], last if !--$nth }

      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart