Reputation: 2047
With regex how can a match everything in a string that isnt something? This may not make sense but read on.
So take the word baby
for instance to match everything that isn't a b
you would do something like [^b]
and this would match a
and y
. Simple enough! But how in this string Ben sits on a bench
can I match everything that isn't ben
so i would be attempting to match sits on a ch
?
Better yet match everything that isn't a pattern? e.g. in 1a2be3
match everything that isn't number,letter,number
, so it would match every combination in the string except 1a2
?
Upvotes: 8
Views: 532
Reputation: 16118
Short answer: You can't do what you're asking. Technically, the first part has an ugly answer, but the second part (as I understand it) has no answer.
For your first part, I have a pretty impractical (yet pure regex) answer; anything better would require code (like @rednaw's much cleaner answer above). I added to the test to make it more comprehensive. (For simplicity, I'm using grep -Pio
for PCRE, case insensitive, printing one match per line.)
$ echo "Ben sits on a bench better end" \
|grep -Pio '(?=b(?!en)|(?<!b)en|e(?!n)|(?<!be)n|[^ben])\w+'
sits
on
a
ch
better
end
I'm basically making a special case for any letter in "ben" so I can include only iterations that are not themselves part of the string "ben." As I said, not really practical, even if I am technically answering your question. I've also saved a blow-by-blow explanation of this regex if you want further detail.
If you're forced into using a pure regex rather than code, your best bet for items like this is to write code to generate the regex. That way you can keep a clean copy of it.
I'm not sure what you're asking for the remainder of your challenge; a regex is either greedy or lazy [1] [2], and I don't know of any implementations that can find "every combination" rather than merely the first combination by either method. If there were such a thing, it would be very very slow in real life (rather than quick examples); the slow speed of regex engines would be intolerable if they were forced to examine every possibility, which would basically be a ReDoS.
Examples:
# greedy evaluation (default)
$ echo 1a2be3 |grep -Pio '(?!\d[a-z]\d)\w+'
a2be3
# lazy evaluation
$ echo 1a2be3 |grep -Pio '(?!\d[a-z]\d)\w+?'
a
2
b
e
3
I assume you are looking for 1
1a
a
a2
a2b
a2be
a2be3
2
2b
2be
2be3
b
be
be3
e
e3
3
but I don't think you can get that with a pure regex. You'd need some code to generate every substring and then you could use a regex to filter out the forbidden pattern (again, this is all about greedy vs lazy vs ReDoS).
Upvotes: 1
Reputation: 659
If you want list of strings, use "split on regexp" instead of "match on regexp".
Upvotes: 0
Reputation: 424983
Just replace everything that matches your pattern with a blank (to delete it).
You haven't indicated what language you are using, so genetically:
s/ben//g
and your other example:
s/\d[a-zA-Z]\d//g
Upvotes: 0
Reputation: 33
Okay The simplest thing To Do is Match Everything
(.*?)
Then on the pattern matched do another Match for What you don't want(for e.g In perl you will have the pattern matched in the variable $&).
If it matches, That's not what you want else you have your match.
Simple A-B where A is everything(.*?) and B is What you don't want.So you end up doing two matches but i think that's fine.
Upvotes: 0
Reputation: 46280
(?:ben)|(.)
What this regex does is match ben
or any other character, however, ben
isn't captured but the other characters are. So you'll end up with a lot of matches except for the ben
's. Then you can join all those matches together to get the string without the ben
's.
Here an example in python.
import re
thestr = "Ben sits on a bench"
regex = r'(?:ben)|(.)'
matches = re.findall(regex, thestr, re.IGNORECASE)
print ''.join(matches)
This will ouput:
sits on a ch
Note the leading space. You can of course get rid of that by adding .strip()
.
Also note, that it is probably faster to do a regex that replaces ben
with an empty string to get the same result. But if you want to use this technique in a more complex regex it could come in handy.
And of course you can also put more complex regexes at the place of ben
, so for example your number,letter,number
example would be:
(?:[0-9][a-z][0-9])|(.)
Upvotes: 1
Reputation: 2373
If you want to match all the words except one, you can use negative lookahead: \b(?!ben\b)\w*\b
, but for an answer to your exact question Jon's comment seems the simplest.
Upvotes: 0