Garance A Drosehn wrote:

> Right now what ruby does is it only saves the *last* copy of
> however many things it matched.  It does seem to me that it
> should save *all* copies of what it matched -- somewhere.
>
> For instance, let's say that Matchdata included another
> method called "repeated", and that method returns an array.
> This array has the same number of elements as captures
> does.  If the pattern-segment for captures[0] is NOT a repeating
> pattern, then repeated[0] returns nil.  If captures[1] is tied to a
> pattern-segment that does (possibly) repeat, then repeated[1]
> returns an array of strings, one element for each time that
> pattern-segment was found.
>
> Eg:
>
>  /^(copy|duplicate) \s+ (\w+\s+)+ (before|after) \s+ (\w+\s*)+ $/x
>
> used to match against the string:
>     "copy apple pear plum peach after bill bob'
>
> $~.captures[0] == "copy"
> $~.repeated[0] == nil
> $~.captures[1] == "peach "
> $~.repeated[1] == {"apple ", "pear ", "plum ", "peach "}
> $~.captures[2] == "after"
> $~.repeated[2] == nil
> $~.captures[3] == "bob"
> $~.repeated[3] == {"bill ", "bob"}
>
> Note that I wouldn't even need to add the extra '()' around
> '(\w+\s+)+' if ruby provided something like this.
>
> Of course, the next question is why not just make captures[1]
> be the array of "things" which were repeatedly matched, instead
> of only holding the last-instance of that repeated pattern.  That
> would work fine, IMO, although I guess it might break the scripts
> of some people.

Looks like a logical and natural extension.  Until it's added, perhaps
something like this would suffice:

pat1 = /\w+\s+/
pat2 = /\w+\s*/
DATA.each {|line|   line.chomp!
  md =
    /^(?:copy|duplicate) \s+
      ((?: #{ pat1 } )+)
      (?:after|before) \s+
      ((?: #{ pat2 } )+) $
    /x.match( line )
  p md.captures
  src_food = md.captures.first.scan( pat1 )
  dest_word = md.captures.last.scan( pat2 )
  p src_food, dest_word
}

__END__
copy apple pear plum peach after bill bob
duplicate tomato before joe alice alfred tommy jane