I need to match members of an array that end with "bar"
but do not start with "foo"
, and put the result in a new array.
Looking at the docs for 1.9.3 and 2.0.0, they seem to support negative look-ahead with the same syntax. Negative look-ahead works as I expect in ruby 2.0.0 but doesn't seem to work in ruby 1.9.3:
["foo a.bar", "b.bar"].grep(/(?!^foo\s).*\.bar$/)
# => ["b.bar"] (ruby 2.0.0)
# => ["foo a.bar", "b.bar"] (ruby 1.9.3)
The ruby version on this infrastructure will be upgraded in 4 months, but changing the version sooner isn't an option. How can I make this work in 1.9.3 and preferably continue to work in 2.0?
Better use this, which looks more convincing:
matched = array.grep(/^(?!foo\s).*\.bar$/)
NOT
starting with foo
this will work in both 2.1.1 and 1.9.3
only if you want to see what I did:
# ruby-1.9.3-p362
array = ["foo a.bar", "b.bar"]
# => ["foo a.bar", "b.bar"]
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["foo a.bar", "b.bar"]
matched = array.grep(/^(?!foo\s).*\.bar$/)
# => ["b.bar"]
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["foo a.bar", "b.bar"]
# ruby-2.1.1
array = ["foo a.bar", "b.bar"]
# => ["foo a.bar", "b.bar"]
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["b.bar"]
matched = array.grep(/^(?!foo\s).*\.bar$/)
# => ["b.bar"]
Simple solution would be not to use negative look-ahead, if it seems problematic in ruby version you are bound to on production servers. If your example is particular enough you could use select
and convenient String methods:
array.select {|str| !str.starts_with?('foo') && str.ends_with?('bar') }
It's your regex that's faulty, not Ruby. Ruby 2 seems to be a little more forgiving, is all.
The start anchor (^
) should be before the lookahead, not in it. When it fails to match foo
at the beginning of the line, the regex engine bumps forward one position and tries again. It's not at the start of the string any more, so ^
doesn't match, the negative lookahead reports success, and the regex matches oo a.bar
. (This is a very common mistake.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With