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 :
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.