How to negate specific word in regex?

2018-12-31 14:03发布

I know that I can negate group of chars as in [^bar] but I need a regular expression where negation applies to the specific word - so in my example how do I negate an actual "bar" and not "any chars in bar"?

标签: regex
10条回答
临风纵饮
2楼-- · 2018-12-31 14:29

You could either use a negative look-ahead or look-behind:

^(?!.*?bar).*
^(.(?<!bar))*?$

Or use just basics:

^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$

These all match anything that does not contain bar.

查看更多
孤独寂梦人
3楼-- · 2018-12-31 14:30

I hope to complement the answer

As the Chris specified Regex Tutorial is a best resource for learning regex.

However, it really consumed time to read through.

I make a cheatsheet for the mnemonic convenience.
[], (), {} leading each class which is easy to recall.

Regex =
{'single_character': ['[]', '.', {'negate':'^'}],
 'capturing_group' : ['()', '|', '\\', 'backreferences and named group'],
 'repetition'      : ['{}', '*', '+', '?', 'greedy v.s. lazy'],
 'anchor'          : ['^', '\b', '$'],
 'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
 'shorthand'       : ['\d', '\w', '\s'],
 }
查看更多
查无此人
4楼-- · 2018-12-31 14:41

Just thought of something else that could be done. It's very different from my first answer, as it doesn't use regular expressions, so I decided to make a second answer post.

Use your language of choice's split() method equivalent on the string with the word to negate as the argument for what to split on. An example using Python:

>>> text = 'barbarasdbarbar 1234egb ar bar32 sdfbaraadf'
>>> text.split('bar')
['', '', 'asd', '', ' 1234egb ar ', '32 sdf', 'aadf']

The nice thing about doing it this way, in Python at least (I don't remember if the functionality would be the same in, say, Visual Basic or Java), is that it lets you know indirectly when "bar" was repeated in the string due to the fact that the empty strings between "bar"s are included in the list of results (though the empty string at the beginning is due to there being a "bar" at the beginning of the string). If you don't want that, you can simply remove the empty strings from the list.

查看更多
听够珍惜
5楼-- · 2018-12-31 14:44

A great way to do this is to use negative lookahead:

^(?!.*bar).*$

The negative lookahead construct is the pair of parentheses, with the opening parenthesis followed by a question mark and an exclamation point. Inside the lookahead [is any regex pattern].

查看更多
墨雨无痕
6楼-- · 2018-12-31 14:46

The accepted answer is nice but is really a work-around for the lack of a simple sub-expression negation operator in regexes. This is why grep --invert-match exits. So in *nixes, you can accomplish the desired result using pipes and a second regex.

grep 'something I want' | grep --invert-match 'but not these ones'

Still a workaround, but maybe easier to remember.

查看更多
几人难应
7楼-- · 2018-12-31 14:47

Unless performance is of utmost concern, it's often easier just to run your results through a second pass, skipping those that match the words you want to negate.

Regular expressions usually mean you're doing scripting or some sort of low-performance task anyway, so find a solution that is easy to read, easy to understand and easy to maintain.

查看更多
登录 后发表回答