使用简单的解析器可能更简单。但是您 can do this 使用 .NET 正则表达式通过使用 balancing groups 并意识到如果从字符串中删除括号,您总是有一个字符串与 ^\d+(?:\s+(?:AND|OR)\s+\d+)*\z 之类的简单表达式匹配。
所以你所要做的就是使用平衡组来确保括号是平衡的(并且在正确的位置以正确的形式)。
稍微改写一下上面的表达式:
(?x)^
OPENING
\d+
CLOSING
(?:
\s+(?:AND|OR)\s+
OPENING
\d+
CLOSING
)*
BALANCED
\z
((?x) 使正则表达式引擎忽略模式中的所有空格和 cmets,因此可以使其更具可读性。)
OPENING 匹配任意数量(包括 0)的左括号:
\s* (?: (?<open> \( ) \s* )*
CLOSING 匹配任意数量的右括号,同时确保平衡组是平衡的:
\s* (?: (?<-open> \) ) \s* )*
和BALANCED 执行平衡检查,如果有更多的开括号然后闭合则失败:
(?(open)(?!))
给出表达式:
(?x)^
\s* (?: (?<open> \( ) \s* )*
\d+
\s* (?: (?<-open> \) ) \s* )*
(?:
\s+(?:AND|OR)\s+
\s* (?: (?<open> \( ) \s* )*
\d+
\s* (?: (?<-open> \) ) \s* )*
)*
(?(open)(?!))
\z
如果您不想让随机空格删除每个\s*。
示例
在IdeOne 上查看演示。输出:
matched: '2'
matched: '1 AND 2'
matched: '12 OR 234'
matched: '(1) AND (2)'
matched: '(((1)) AND (2))'
matched: '1 AND 2 AND 3'
matched: '1 AND (2 OR (3 AND 4))'
matched: '1 AND (2 OR 3) AND 4'
matched: ' ( 1 AND ( 2 OR ( 3 AND 4 ) )'
matched: '((1 AND 7) OR 6) AND ((2 AND 5) OR (3 AND 4))'
matched: '(1)'
matched: '(((1)))'
failed: '1 2'
failed: '1(2)'
failed: '(1)(2)'
failed: 'AND'
failed: '1 AND'
failed: '(1 AND 2'
failed: '1 AND 2)'
failed: '1 (AND) 2'
failed: '(1 AND 2))'
failed: '(1) AND 2)'
failed: '(1)() AND (2)'
failed: '((1 AND 7) OR 6) AND (2 AND 5) OR (3 AND 4))'
failed: '((1 AND 7) OR 6) AND ((2 AND 5 OR (3 AND 4))'
failed: ''