Dave
Dave

Reputation: 19220

How do I match a regex provided that the word after my reg is not equal to a certain string?

I'm using Rails 5 and Ruby 2.4. I'm confused about how to match a regular expression in which the word following is not equal to a certain thing. I want to match a number, a "/" and another number provided that the word after is not equal to "aaa". So this would match

1/3 ddd

as would

7/10 eee

and also

33/2

but not

4/555aaa

or

4/5 aaa

I have figured out how to craft my regex this far ...

2.4.0 :006 > re = /\d+[[:space:]]*\/[[:space:]]*\d+/
 => /\d+[[:space:]]*\/[[:space:]]*\d+/
...
2.4.0 :009 > string = "1/2 aaa"
 => "1/2 aaa"
2.4.0 :010 > string.match(re)
 => #<MatchData "1/2">

but I don't know how to add the clause about "the last word shall not be 'aaa'". How do I do that?

Upvotes: 1

Views: 134

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627103

I sugges using a negative lookahead (?![[:space:]]*aaa) combined with a possessive ++ quantifier after last \d:

/\d+[[:space:]]*\/[[:space:]]*\d++(?![[:space:]]*aaa)/
                                ^^^^^^^^^^^^^^^^^^^^^

See the Rubular demo

Details

  • \d+ - 1 or more digits
  • [[:space:]]* - zero or more whitespaces
  • \/ - a forward slash
  • [[:space:]]* - zero or more whitespaces
  • \d++ - 1 or more digits, matched possessively, so that the negative lookahead that follows could not make the engine backtrack into this subpattern (and yield a smaller portion of digits that are not followed with the lookahead pattern)
  • (?![[:space:]]*aaa) - the negative lookahead that fails the match if there is no 0+ whitespaces and aaa immediately to the right of the current location.

Upvotes: 1

Related Questions