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
?
(wildcard character) match anything, including line breaks. Throw in an * (asterisk), and it will match everything. Read more. \s (whitespace metacharacter) will match any whitespace character (space; tab; line break; ...), and \S (opposite of \s ) will match anything that is not a whitespace character.
Definition and Usage. The ?! n quantifier matches any string that is not followed by a specific string n.
The uppercase counterpart \D (non-digit) matches any single character that is not a digit (same as [^0-9] ). \s (space) matches any single whitespace (same as [ \t\n\r\f] , blank, tab, newline, carriage-return and form-feed).
By default, the '. ' dot character in a regular expression matches a single character without regard to what character it is. The matched character can be an alphabet, a number or, any special character.
(?: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])|(.)
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).
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