Andrew Johnson wrote: > William James wrote: > > Andrew Johnson wrote: > >> If I am reading your specs correctly: > >> > >> /^(((?!\[joe\]).)*(\[joe\]((?!\[joe\]).)+\[\/joe\])){1,3}((?!\[joe\]).)*$/ > > > > [ > > "good [joe] [/joe] [joe] [/joe]", > > "bad [/joe] [joe] [/joe]", > > "bad [joe] [/joe] [/joe]" > > ].each { |s| > > p s =~ > > /^(((?!\[joe\]).)*(\[joe\]((?!\[joe\]).)+\[\/joe\])){1,3}((?!\[joe\]).)*$/ > > } > > Quite right: > > [ > "good [joe] [/joe] [joe] [/joe]", > "bad [/joe] [joe] [/joe]", > "bad [joe] [/joe] [/joe]" > ].each { |s| > p s if s =~ > /^(((?!\[\/?joe\]).)*(\[joe\]((?!\[\/?joe\]).)+\[\/joe\])){1,3}((?!\[\/?joe\]).)*$/ > } > > cheers > andrew Yours is faster for very short strings; longer strings allow the array method to pull ahead. require 'benchmark' $n = 10_000 $strings = [ "good [joe] Wasn't that what [i]he[/i] was seeking? [/joe] [joe] Can't you [b]see[/b] that? [/joe]", "bad was Peck's boy [/joe] [joe] But he'll never know. [/joe]", "bad to the bone [joe] Or will he?! [/joe] mish mash mush Marching on Tom Tidler's ground fatigues me. [/joe]", "bad: too many [joe] [/joe] [joe] [/joe] [joe] [/joe] [joe] [/joe]", "bad: too few" ] def regexp $regexp_good = 0 $n.times{ $strings.each { |s| $regexp_good += 1 if s =~ /\A(((?!\[\/?joe\]).)*(\[joe\]((?!\[\/?joe\]).)+\[\/joe\])){1,3}((?!\[\/?joe\]).)*\Z/m } } end def array $array_good = 0 $n.times{ $strings.each { |s| ary = s.scan( %r{\[/?joe\]} ) if [2,4,6].include?(ary.size) and ary == ary.partition{|t| "[joe]"==t}.inject{|a,b| a.zip(b)}. flatten $array_good += 1 end } } end Benchmark.bmbm do |x| x.report("regexp") { regexp } x.report("array") { array } end puts ; p $regexp_good, $array_good Rehearsal ------------------------------------------ regexp 6.870000 0.000000 6.870000 ( 7.391000) array 2.653000 0.000000 2.653000 ( 2.874000) --------------------------------- total: 9.523000sec user system total real regexp 6.940000 0.000000 6.940000 ( 7.441000) array 2.634000 0.000000 2.634000 ( 2.854000) 10000 10000