'Match repeating groups with regex with optional parameter in .NET
I need to validate a filtering input with a regex that will be used for a [RegularExpression] attribute on a Filter field in a class used a input model. The input has the following format:
[property]~[predicate]~[value]
For example:
lastname~eq~'John'
and also multiple filtering can be applied n times:
[property]~[predicate]~[value]~[logicaloperator]~[property]~[predicate]~[value] ...
For example:
lastname~eq~'Doe'~and~firstname~eq~'John'~or~firstname~eq~'Jane'
I have to make sure that if logical operators are used then they are followed by the same pattern. I tried using named groups and lookbehinds but I couldn't get it to work properly.
I've created the following regex :
((((\w+)~(\blt\b|\blte\b|\beq\b|\bgt\b|\bgte\b|\bneq\b|\bcontains\b)~(.\w+.))(~(\bor\b|\band\b)~)?((\w+)~(\blt\b|\blte\b|\beq\b|\bgt\b|\bgte\b|\bneq\b|\bcontains\b)~(.\w+.))?)+)
I cannot get it to match only when the input is valid. The general pattern of the groups that I've tried to implement is:
(main group-
(property group-any word)~(predicate group-list of operators)~(value -any value)
)
(~(logic operator)~)
(main group)
Targeted behavior:
Valid input:
lastname~eq~'Doe' -> should match
lastname~eq~'Doe'~and~firstname~eq~'John' -> should match
lastname~eq~'Doe'~and~firstname~eq~'John'~or~firstname~eq~'Jane' -> should match
Invalid input:
lastname~eq~ ->should not match
lastname~eq~'Doe'~and~firstname~eq ->should not match
lastname~eq~'Doe'~and~firstname~eq~John~ ->should not match
lastname~eq~'Doe'~and~firstname~eq~John~or~ ->should not match
Any ideas how to make this work ?
Solution 1:[1]
You can use
^\w+~(?:lte?|n?eq|gte?|contains)~['"][^'"]+['"](?:~(?:and|or)~\w+~(?:lte?|n?eq|gte?|contains)~['"][^'"]+['"])*$
Or,
^(?:\w+~(?:lte?|n?eq|gte?|contains)~['"][^'"]+['"](?:~(?:and|or)~(?!$)|$))+$
See the regex demo.
Note that the $ is preceded with \r? in the regex demo because the string is a multiline string with CRLF line endings, and RegexOptions.Multiline option is enabled.
The pattern matches
^- start of string\w+- one or more word chars~- a~char(?:lte?|n?eq|gte?|contains)- a predicate pattern (lt,lte,gt,gte,neq,eq,contains~- a~char['"][^'"]+['"]- a'or", then one or more chars other than'and"and then a"or'(?:- start of a non-capturing group~(?:and|or)~-~,andoror, and a~char\w+~(?:lte?|n?eq|gte?|contains)~['"][^'"]+['"]- described above
)*- zero or more repetitions$- end of string.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Wiktor Stribiżew |
