From: Anthony Durity Date: 2006-02-07T02:24:42+09:00 Subject: Re: Merging regular expressions Jacob, Brilliant! But... see my last post, i want to avoid iteration by merging all regexps into one large regexp. However, this is absolutely beautiful and correct. Taken with the replies I got earlier this is a great start. Question... What would the following code output? r = [] r << /aaa/ r << /[ab][ab][ab]/ m = Regexp.union( *r ) m =~ "aaa" # => ? (I think I basically want to be able to twiddle with the finite automata the regexps make when they are compiled/created, I dunno if this is possible) Later, Anthony On 2/6/06, Jacob Fugal wrote: > On 2/6/06, Anthony Durity wrote: > > r[0] = /a/ > > r[1] = /b/ > > m = Regexp.union(r0.source, r1.source) > > # _but_ when I go to check s with > > m =~ s > > # if it matches, i want it to tell me which of the original r[i] would have matched! > > How about: > > class Regexp > class Union > def initialize( *regexen ) > @regexen = regexen > end > > def <<( regex ) > @regexen << regex > end > > def =~( other ) > regexen = @regexen.select{ |regex| regex =~ other } > raise "ambiguous input" if regexen.size > 1 > return nil if @regexen.empty? > return @regexen.index(regexen[0]) > end > > def []( index ) > @regexen[index] > end > end > > def self.union( *regexen ) > Regexp::Union.new( *regexen ) > end > end > > Usage: > > r = [] > r << /a/ > r << /b/ > m = Regexp.union( *r ) > m =~ "a test" # => 0 > m =~ "test b" # => 1 > m =~ "none" # => nil > m =~ "ambiguous" # raises "ambiguous input" > > Jacob Fugal > >