regex contains all and only

Viewed 49

I have a list of allowed fruits and have to ensure that the config file contains all these and only these fruits each in a seperate line as below.The config file has other config lines.Lets say the allowed fruits are apple,banana,cherry then then the valid config file would look like:

fruit apple  
some other config line
############
fruit banana

fruit cherry
other config 1

other config n

Any idea of a java regex to check if all the three allowed fruits are listed and only those fruits.For eg: if a fourth fruit is listed in a seperate line then the config file is invalid.

I could achieve with two regexes.One for must contain all and the second to check that it does not contain any other:

Positive - contain all
^(?=.*?^fruit banana)(?=.*?^fruit cherry)(?=.*?^fruit apple).*$
Must not contain anything else
^fruit (?!apple|banana|cherry)

Can anybody come up with just one regex??Thanks.

2 Answers

Here's a regular expression that should fit your description:

^((?!\bfruit\b).)*  # nothing with "fruit" before
( # then, either:
# 1. fruit apple, followed by things that are not "fruit", followed by fruit banana, non-fruits, and then fruit cherry, or vice versa
\bfruit\b\ apple((?!\bfruit\b).)*(\bfruit\b\ banana((?!\bfruit\b).)*fruit\ cherry|fruit\ cherry((?!\bfruit\b).)*fruit\ banana)
|
# 2. Same with banana at the beginning
fruit\ banana((?!\bfruit\b).)*(fruit\ apple((?!\bfruit\b).)*fruit\ cherry|fruit\ cherry((?!\bfruit\b).)*fruit\ apple)
|
# 3. And with cherry
fruit\ cherry((?!\bfruit\b).)*(fruit\ apple((?!\bfruit\b).)*fruit\ banana|fruit\ banana((?!\bfruit\b).)*fruit\ apple)
)
((?!\bfruit\b).)*$ # no more fruit

Since I have no idea about how Java regexes work, I made this with Python's verbose regex mode, to be able to write them a little less terse, but this should be translatable in any capable regex engine.

Demo

Join your lookaheads:

(?ms)^(?!.*?^fruit (?!apple|banana|cherry))(?=.*?^fruit banana)(?=.*?^fruit cherry)(?=.*?^fruit apple).*$

See proof it works.

The (?!.*?^fruit (?!apple|banana|cherry)) at start will make sure there is no line that starts with fruit that is followed with space and then has no apple, banana or cherry.

Related