From: Brian Candler Date: 2003-04-24T16:44:50+09:00 Subject: Re: grep and regular expressions in ruby On Thu, Apr 24, 2003 at 08:00:55AM +0900, Krishna Dole wrote: > I'm quite taken with ruby, but recently I ran into trouble using grep. I > have two questions: first, is there a way to call grep with multiple > regexps? For example, if you had > ar = ["cat", "dog", "smallcat"] > > and you only wanted strings matching both "small" and "cat", in perl I > think you could do something like > ar2 = grep(( /cat/ and /small/ ), ar ); To make this run I had to add some $ signs in front of your variable names :-) The reason this works in Perl is because you are doing two separate regexp comparisons. The syntax /foo/ is shorthand for $_ =~ /foo/ and 'grep' assigns $_ for each iteration, making it like a block parameter in Ruby. So the direct Ruby translation is ar2 = ar.select(|e| e =~ /cat/ and e =~ /small/) In Perl you drop the '|e| e=~' because it's implicit on $_ There are many Ruby methods which try to simulate this behaviour on $_ by being methods of Kernel, for example Kernel#chomp! is essentially $_.chomp!, and because Kernel is included in Object, you can just write 'chomp!' But this doesn't work for a standalone regular expressions. In Ruby you definitely don't want /foo/ to mean $_ =~ /foo/, because myregexp = /foo/ # build a regexp object is useful and definitely not the same as myregexp = $_ =~ /foo/ # build and match a regexp object Personally I think Ruby borrows too much from Perl already in this way; I would happily see $_ stricken from the language completely, and all the polluted methods in Kernel removed. In other words, I'd deprecate while gets chomp! gsub!(/foo/,'bar') # etc end in favour of: while line = gets line.chomp! line.gsub!(/foo/,'bar') # etc end Somebody once did propose, and I think even implement, a default object receiver: something like while line = gets with line do chomp! gsub!(/foo/,'bar') # etc end end For the duration of the block, *self* is set to 'line'. That IMO is much more Rubyish than having a bunch of methods all act on the shared global variable $_ Anyway, I digress :-) > ar2 = grep(( /cat/ and !/small/ ), ar ); > > but '!' doesn't work for me in ruby. There is e !~ /foo/ which is shorthand for !(e =~ /foo/) Regards, Brian.