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

Let’s say that I've got a very long string which I know to contain zero-or-more occurrences of the substring FOO something... BAR.   And, let’s say that I know exactly how to construct a regular-expression that will correctly identify an occurrence of that substring, grab the piece I want out of it, etc.   (“How to construct that regex,” then, is not the question.)

What has escaped my dim memory is ... what is the “elegant, perlish way” to produce, say, a list or an array of all of those occurrences, i.e. “all at once?”

If there were (say...) five occurrences of a matching pattern in the big, long string, the result would be a list or array with five entries.

Replies are listed 'Best First'.
Re: Grab "as many occurrences as there are" in a long string
by SuicideJunkie (Vicar) on Sep 23, 2010 at 20:48 UTC
    use warnings; use strict; use Data::Dumper; my $string = "A dun dun B ignorable A something B\n"; my @contents = $string =~ /A (.*?) B/g; print Dumper \@contents;
    Will output:
    $VAR1 = [ 'dun dun', 'something' ];
    With the key bits being the use of /g and assigning in list context.

    If your strings can possibly overlap each other, then you've got more work to do, but it sounds like that is not the case here.

Re: Grab "as many occurrences as there are" in a long string
by JavaFan (Canon) on Sep 23, 2010 at 21:31 UTC
    Actually, depending on what something is, it's either easy, or somewhat harder to do with a regexp. For instance, if something is /.*/, than the string
    "zero FOO one two BAR three FOO four five BAR six"
    contains three occurrences of "FOO something BAR". You can still get all matches with a regexp:
    $_ = "zero FOO one two BAR three FOO four five BAR six"; /(FOO.*BAR)(??{ say $1 })(*FAIL)/; __END__ FOO one two BAR three FOO four five BAR FOO one two BAR FOO four five BAR

      Now... that is “Regexp Voodoo!”  :-D

      “Surely, I am standing in the presence of a Greater Perl Being,™” he said humbly.

      I was thinking about the “greedy” modifier, and how one would need to use this to avoid simply matching the entire string in a case like the one you have cited.   I am quite befuddled by the incantation you have so wisely uttered here.   Where can I perldoc to read more about such Higher Magick, that I may one day Impress My Friends, too?

        I was thinking about the “greedy” modifier, and how one would need to use this to avoid simply matching the entire string in a case like the one you have cited.
        Ah, you mean as in "something equals /.*?/"? Then here's a question for you. How many times does "FOO.*?BAR" occur in "zero FOO one FOO two BAR three BAR four"?
        Where can I perldoc to read more about such Higher Magick, that I may one day Impress My Friends, too?
        Except for say, all will be revealed by reading man perlre. (Oh, and if you replace "(*FAIL)" with "(?!)", you could have done the trick ever since 5.005 - it's not something from this century).

        Note also that

        /(FOO.*?BAR)(??{ say $1 })(*FAIL)/;
        and
        /(FOO.*BAR)(??{ say $1 })(*FAIL)/;
        print exactly the same matches, although in a possible different order.
Re: Grab "as many occurrences as there are" in a long string
by repellent (Priest) on Sep 24, 2010 at 17:53 UTC
    See Regexp::Exhaustive. Following up on SuicideJunkie's example, with overlaps:
    use Regexp::Exhaustive qw(exhaustive); use Data::Dumper; my $str = "A dun A dun B overlapped B something A again B"; print Dumper [ exhaustive($str => qr/A (.*?) B/) ]; __END__ $VAR1 = [ "dun A dun", "dun A dun B overlapped", "dun A dun B overlapped B something A again", "dun", "dun B overlapped", "dun B overlapped B something A again", "again" ];