Lets say I have the following string: "BENffew123X\r\nBENx432f456X\r\nBEN!233789X\r\nBEN4545789X"
I want to have a regex that will catch "BEN!233789", it has to lookup non-greedily for "BEN", followed by any character (excluding the word "BEN") and ending with 789X. I tried the regex: /BEN.+?789X/mi
and I get "BENffew123X\r\nBENx432f456X\r\nBEN!233789X"
as a match.
I understand that this regex looks for the first "BEN" and catches the start of the string, but I want it to look for the "BEN" which is closest to the first "789X". How can I achieve that? One Idea is to reverse the string, should I do it?
Asked
Active
Viewed 1.5k times
15

benams
- 4,308
- 9
- 32
- 74
1 Answers
24
You need to make sure that BEN
isn't present in the text between BEN
and 789X
. You can do this using a negative lookahead assertion:
/BEN(?:(?!BEN).)*?789X/mi
See it live on regex101.com.
Explanation:
BEN # Match "BEN"
(?: # Start of non-capturing group that matches...
(?!BEN) # (if "BEN" can't be matched here)
. # any character
)*? # Repeat any number of times, as few as possible
789X # Match 789X

Tim Pietzcker
- 328,213
- 58
- 503
- 561
-
What does `*?` mean ? – Arup Rakshit Feb 09 '14 at 12:48
-
2Non-greedy `*` (as comment says 'as few as possible'). – Michael Kohl Feb 09 '14 at 12:49
-
1@ArupRakshit: "Zero or more repetitions (`*`), as few as possible (`?`)". So if you have `BEN...789X...789X` it will stop the match at the first `789X`. – Tim Pietzcker Feb 09 '14 at 12:49
-
1@TimPietzcker Thanks. I understand now from this - [how to make Regular expression into non-greedy?](http://stackoverflow.com/questions/2824302/how-to-make-regular-expression-into-non-greedy) – Arup Rakshit Feb 09 '14 at 12:52
-
Wrapping the negative lookahead in a non-capturing group is a really great idea -- especially if, like me, you're fixing a bug in an existing system and the later logic depends on the exact set of captures. Have an upvote! – Jazz Feb 03 '17 at 17:20