Looking for a bit of regex help. I\'d like to design an expression that matches a string with \"foo\" OR \"bar\", but not both \"foo\" AND \"b
I'd use something like this. It just checks for space around the words, but you could use the \b
or \B
to check for a border if you use \w
. This would match " foo " or " bar ", so obviously you'd have to replace the whitespace as well, just in case. (Assuming you're replacing anything.)
/\s((foo)|(bar))\s/
If your regex language supports it, use negative lookaround:
(?<!foo|bar)(foo|bar)(?!foo|bar)
This will match "foo" or "bar" that is not immediately preceded or followed by "foo" or "bar", which I think is what you wanted.
It's not clear from your question or examples if the string you're trying to match can contain other tokens: "foocuzbar". If so, this pattern won't work.
Here are the results of your test cases ("true" means the pattern was found in the input):
foo: true
bar: true
foofoo: false
barfoo: false
foobarfoo: false
barbar: false
barfoofoo: false
I tried with Regex Coach against:
x foo y
x bar y
x foobar y
If I check the g
option, indeed it matches all three words, because it searches again after each match.
If you don't want this behavior, you can anchor the expression, for example matching only on word boundaries:
\b(foo|bar)\b
Giving more context on the problem (what the data looks like) might give better answers.
This will take 'foo' and 'bar' but not 'foobar' and not 'blafoo' and not 'blabar':
/^(foo|bar)$/
^ = mark start of string (or line)
$ = mark end of string (or line)
This will take 'foo' and 'bar' and 'foo bar' and 'bar-foo' but not 'foobar' and not 'blafoo' and not 'blabar':
/\b(foo|bar)\b/
\b = mark word boundry
You might want to consider the ? conditional test.
(?(?=regex)then|else)
Regular Expression Conditionals
\b(foo)\b|\b(bar)\b
And use only the first capture group.