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

Hi, I was trying some perl regex and got a bit stuck while trying to print index values in ranges. Have a look at my code.

#!/iusr/bin/perl open(FH, $ARGV[0]) || die("Cannot Open:$!"); while(<FH>){ $char = '-'; $offset = 0; $result = index($_, $char, $offset); while ($result != -1) { print "Found $char at $result\n"; $offset = $result + 1; $result = index($string, $char, $offset); } }

This code prints the location of "-" wherever it finds... e,g

A-----B

if it finds this character it will print the location 5 times.

found at 2

found at 3

found at 4

found at 5

found at 6

I wanted to print the range when it finds this type of case.

Means

found at 2 to 6

Any suggestion ?

Thanks in advance

Replies are listed 'Best First'.
Re: Regular Expression Search
by Eliya (Vicar) on Feb 09, 2012 at 18:38 UTC

    You're better off using a regex for this.  In particular, a m//g (global) match in scalar context:

    my $char = '-'; while (<DATA>) { print; while (/($char+)/g) { my $to = pos(); my $from = $to - length($1) + 1; print " Found $char at $from to $to\n"; } } __DATA__ A-----B A----C---B

    Output:

    A-----B Found - at 2 to 6 A----C---B Found - at 2 to 5 Found - at 7 to 9

    See m//g and pos.

      Thanks !

Re: Regular Expression Search
by CountZero (Bishop) on Feb 09, 2012 at 21:39 UTC
    With the use of Number::Rangify and some maps and a grep:
    use Modern::Perl; use Number::Rangify qw/rangify/; while (<DATA>) { my $seq; my @ranges = map { sprintf "%s-%s", $_->Size } rangify( grep $_, map { $seq++; $_ eq '-' ? $seq : '' } split // + ); say "@ranges"; } __DATA__ A---B A--B---C ABC--DE A-B--C----DEF------H
    Output:
    2-4
    2-3 5-7
    4-5
    2-2 4-5 7-10 14-19
    

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Regular Expression Search
by Riales (Hermit) on Feb 09, 2012 at 19:05 UTC

    Others have already shown you a better way to go, but here's an implementation using index just for fun:

    #!/usr/bin/perl use strict; use warnings; sub find_char { my ($char, $string) = @_; my @indexes_present = (); my $position = 0; while (length($string)) { my $index = index($string, $char); if ($index != -1) { $position = $position + ($index+1); push @indexes_present, $position; $string = substr($string, ($index+1), (length($string)-$in +dex)); } else { last; } } push @indexes_present, -1; my ($start_of_range, $end_of_range); my $previous_index; while (my $index = shift @indexes_present) { if (!defined($previous_index)) { $start_of_range = $end_of_range = $index; } elsif (($previous_index+1) == $index) { $end_of_range = $index; } else { if ($start_of_range == $end_of_range) { print "Found at $start_of_range\n"; } else { print "Found at $start_of_range to $end_of_range\n"; } $start_of_range = $end_of_range = $index; } $previous_index = $index; } } while (<DATA>) { print "\n$_"; find_char('-', $_); } __DATA__ A--B---C----D-E A-B--C---D----E ---------------

    Prints:

    A--B---C----D-E Found at 2 to 3 Found at 5 to 7 Found at 9 to 12 Found at 14 A-B--C---D----E Found at 2 Found at 4 to 5 Found at 7 to 9 Found at 11 to 14 --------------- Found at 1 to 15 Press ENTER or type command to continue

    So yeah. The other way is better.

Re: Regular Expression Search
by InfiniteSilence (Curate) on Feb 09, 2012 at 18:43 UTC
    ~linux>perl -e '$BEGIN{my @found = ()}; $foo = q|A--B|; while($foo=~m/ +\-/g){push @found,@+}; END{print qq|found at $found[0] to $found[$#fo +und]|}'
    Prints
    found at 2 to 3

    Celebrate Intellectual Diversity

Re: Regular Expression Search
by trizen (Hermit) on Feb 10, 2012 at 08:57 UTC
    while (<DATA>) { print; while (/-+/g) { printf "Found at %s\n", $-[0]+1 . ($+[0] != $-[0]+1 ? " to $+[ +0]" : ''); } } __DATA__ A-----B A----C---B A--B---C----D-E A-B--C---D----E ---------------