I am trying to come up with a Ruby Regex that will match the following string:
MAINT: Refactor something
STRY-1: Add something
STRY-2: Update something
But should not match the following:
MAINT: Refactored something
STRY-1: Added something
STRY-2: Updated something
MAINT: Refactoring something
STRY-3: Adding something
STRY-4: Updating something
Basically, the first word after :
should not end with either ed
or ing
This is what I have currently:
^(MAINT|(STRY|PRB)-\d+):\s([A-Z][a-z]+)\s([a-zA-Z0-9._\-].*)
I have tried [^ed]
and [^ing]
but they would not work here since I am targeting more than single character.
I am not able to come up with a proper solution to achieve this.
You could use
^[-\w]+:\s*(?:(?!(?:ed|ing)\b)\w)+\b.+
See a demo on regex101.com.
^ # start of the line/string
[-\w]+:\s* # match - and word characters, 1+ then :
(?: # non-capturing group
(?!(?:ed|ing)\b) # neg. lookahead: no ed or ing followed by a word boundary
\w # match a word character
)+\b # as long as possible, followed by a boundary
.* # match the rest of the string, if any
Ruby
but I guess you could alternatively do a split and check if the second word ends with ed
or ing
. The latter approach might be easier to handle for future programmers/colleagues.
r = /
\A # match beginning of string
(?: # begin a non-capture group
MAINT # match 'MAINT'
| # or
STRY\-\d+ # match 'STRY-' followed by one or more digits
) # end non-capture group
:[ ] # match a colon followed by a space
[[:alpha:]]+ # match one or more letters
(?<! # begin a negative lookbehind
ed # match 'ed'
| # or
ing # match 'ing'
) # end negative lookbehind
[ ] # match a space
/x # free-spacing regex definition mode
"MAINT: Refactor something".match?(r) #=> true
"STRY-1: Add something".match?(r) #=> true
"STRY-2: Update something".match?(r) #=> true
"MAINT: Refactored something".match?(r) #=> false
"STRY-1: Added something".match?(r) #=> false
"STRY-2: Updated something".match?(r) #=> false
"A MAINT: Refactor something".match?(r) #=> false
"STRY-1A: Add something".match?(r) #=> false
This regular expression is conventionally written as follows.
r = /\A(?:MAINT|STRY\-\d+): [[:alpha:]]+(?<!ed|ing) /
Expressed this way the two spaces can each be represented a space character. In free-spacing mode, however, all spaces outside character classes are removed, which is why I needed to enclose each space in a character class.
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