From: Robert Klemme Date: 2009-01-13T04:39:18+09:00 Subject: Re: Does ruby support global expression? On 12.01.2009 15:33, Robert Dober wrote: > On Mon, Jan 12, 2009 at 2:59 PM, Jarod Zhu wrote: >> Hi, all >> >> In my project, there are some rules using global expression( '*' >> as one or more characters ) to match some functions' output. >> Such as: >> rule1: the * apple (will match the output "the red apple") >> rule2: the * + * game (will match the output "the wonderful + >> successful game") >> >> I want to use ruby to realize the match check, but I only know >> ruby supports regular expression. >> So I have to change rules to the form of regular expressions( "*" => ". >> +" and add '\' to other regular expession keywords like '+', '.' etc.) >> >> Is there any way to use global expression directly in ruby? > No, better make it ourselves > > class String > def escape > return "" if empty? > Regexp::escape self > end > def glob? a_string > Regexp::new( > scan( /(.*?)\*([^*]*)/ ). > inject("") { | r , ( prefix, suffix ) | r << prefix.escape << > '\w+' << suffix.escape } > ).match( a_string ) > end > end > > p "ab *c*d*".glob?( "ab andcordequally" ) > p "a*b".glob?( "ab" ) > p "etc.etc." Small remark: I'd split this up, i.e. class String def to_glob Regexp::new( scan( /(.*?)\*([^*]*)/ ). inject("") { | r , ( prefix, suffix ) | r << prefix.escape << '\w+' << suffix.escape } ) end end This makes for more efficient matching if the pattern is to be applied to multiple strings. Here's how I'd do it: class String def to_glob Regexp.new('\\A' << gsub(/\\([^*?])/, '\\1').split(/(\\?[*?])/).map do |s| case s when '*': '.*' when '?': '.' when '\\*', '\\?': s else Regexp.escape(s) end end.join << '\\z') end end gl = "foo*b\\ar\\*a".to_glob p gl %w{foo foobar*a foo123bar foobar*a}.each do |s| p [s, gl =~ s] end Kind regards robert -- remember.guy do |as, often| as.you_can - without end