C# 如何生成递归正则表达式
我想创建一个能够为我匹配一些逻辑公式的正则表达式,以验证输入 基本上,我会有一个数字(0-100),一个关键字(和/或)和括号 因此,我应该能够匹配此类用例:C# 如何生成递归正则表达式,c#,.net,regex,C#,.net,Regex,我想创建一个能够为我匹配一些逻辑公式的正则表达式,以验证输入 基本上,我会有一个数字(0-100),一个关键字(和/或)和括号 因此,我应该能够匹配此类用例: 1 AND 2 (1 AND 2) OR 3 1 AND (2 OR 3) (1 AND 2) OR (3 AND 4) 1 AND (2 OR (3 AND (4 OR 5))) 我不需要验证它是最简单的表单(比如阻止用户编写(1和(2和3)) 到目前为止,我已经创建了以下内容: \(?(\d+)\s+(AND|OR)\s+\d+\)
1 AND 2
(1 AND 2) OR 3
1 AND (2 OR 3)
(1 AND 2) OR (3 AND 4)
1 AND (2 OR (3 AND (4 OR 5)))
我不需要验证它是最简单的表单(比如阻止用户编写(1和(2和3))
到目前为止,我已经创建了以下内容:
\(?(\d+)\s+(AND|OR)\s+\d+\)?
但我有几件事要做:
\d+
或相同的整个表达式正则表达式:语法规则,它解析规则的和通常的非递归结构,一般不解析递归结构,如:JSON、HTML、数学表达式、布尔表达式、C++、C语言、java等。它不适合其他语法,正则表达式在有限状态自动机上工作,而任务涉及上下文。(这就是为什么需要堆栈),因此您应该使用下一级语法层次结构:
您通常希望通过使用带有堆栈的硬编码自动机(如注释中建议的)或使用框架根据LR/LL语法解析输入来完成的工作:ANTLR、Gold、pegasus等 例如,ANTLR有很多语法:github.com/ANTLR/grammars-v4。 如果深入研究一下语法,你会发现你的问题在多个语法中都有答案:< /P> < P>正则表达式:java语法规则,它解析规则的,通常是非递归的结构,一般不解析递归结构,如:JSON、HTML、数学表达式、布尔表达式、C++、C语言、Java等。它不适合其他语法,正则表达式在有限状态自动机上工作,而任务涉及CON。文本(这就是为什么需要堆栈),因此您应该使用下一级语法层次结构:
您通常希望通过使用带有堆栈的硬编码自动机(如注释中建议的)或使用框架根据LR/LL语法解析输入来完成的工作:ANTLR、Gold、pegasus等 例如,ANTLR有很多语法:github.com/ANTLR/grammars-v4。 如果深入研究一下语法,你会发现你的问题在多个语法中都有答案:你在工作中使用了错误的工具。.NET正则表达式不提供递归,特别是我不确定它是否能识别所有的CFG,这本身就是一个有趣的问题。因此,如果你的问题是,嗯,学术兴趣,那么你可以提前阅读。如果你真的想在某些产品中使用它那么,请不要使用密码 也就是说,为了匹配括号,您可以使用。根据匹配尖括号的文档改编示例,您将得到以下结果:
^[^\(\)]*(((“打开”\()[^\(\)]*)+(((“关闭-打开”\)[^\(\)]*)+)*(((打开)(?!)$
括号内的内容由上面的表达式[^\(\)]*
定义。我没有成功地尝试将数字和/或规则纳入其中,同时又没有失去理智,并创建了一个长度远远超过联邦法规的正则表达式
但是,我们可以结合使用多个正则表达式来验证您的输入。首先,请忽略括号,并确保表达式的一般形式为number(和/或number)*
:
^[\(\)]*([0-9][1-9][0-9][100](\s(和/或)\s[\(\)]*([0-9][1-9][0-9][100][\(\)]*)*$
上述模式已排除空括号和带有单个数字的括号。仍需排除使用多个和/或在单个括号内的字符串,如1或2和3
或1或(2和3和4)
或1和2或(1和2)
(\d)+\s*(和|或)\s*(\d)+\s*(和|或)
因此,要验证您的输入,您需要运行所有三个正则表达式,并断言前两个匹配,而最后一个不匹配
顺便说一句,您可能可以将这三个正则表达式用作分支指令,并组合成一个单独的正则表达式,该正则表达式声明与前两个正则表达式匹配,而与最后一个正则表达式不匹配。这是留给读者的一个练习,因为这同样是不可读的
您可以找到一个工作正常的dotnetfiddle演示。以下代码供参考:
使用系统;
使用System.Text.RegularExpressions;
var-correctoreparanthesis=newregex(@“^[^\(\)]*(((?'Open'\()[^\(\)]*)+(((?'Close-Open'\))[^\(\)]*)+(?(Open)(?!)$);
var correctStructure=new Regex(@“^[\(\)]*([0-9]|[1-9][0-9]|[100”)(\s(和|或)\s[\(\)]*([0-9]|[1-9][0-9]| 100][\(\)*)”;
var ambiguousClauses=新正则表达式(@“(\d)+\s*(和|或)\s*(\d)+\s*(和|或)”;
bool验证(字符串输入)=>
!string.IsNullOrWhiteSpace(输入)&&
修正了IsMatch(输入)和
更正结构。IsMatch(输入)和
!ambiguousClauses.IsMatch(输入);
var validInputs=新[]
{
“1和2”,
“(1和2)或3”,
“1及(2或3)”,
“(1及2)或(3及4)”,
“1及(2或(3及(4或5))”,
“(((1及2)或(3)及(4)或(5)”,
"1"
};
var invalidinput=new[]
{
“(1和2)或3”,
“((1和2)或3”,
"(1)",
"()",
"101",
“1和2”,
“及1及”,
“和”,
“1和2”,
“1或2和3”,
“1或(2及3及4)”,
“1及2或(1及2)”
};
foreach(var validInput在validInputs中)
{
var isValid=验证(validInput);
如果(!isValid)
{
抛出新异常($“有效输入{validInput}未验证。”);
}
}
foreach(var INVALIDIPUT in INVALIDIPUTS)
{
var isValid=验证(invalidInput);
如果(有效)
{
抛出新异常($“无效输入{invalidInput}已验证”);
}
}
控制台。WriteLine(“所有案例均通过”);