用于检测以分号结尾的C++;for&;while循环 在Python应用程序中,我需要编写一个与C++代码< > > >代码> >的正则表达式,而循环已经用一个半冒号终止了(;)。例如,它应该与以下内容匹配: for (int i = 0; i < 10; i++);
有人能建议对这个正则表达式进行改进吗?这对我来说太复杂了,我想不起来了。这是你真的不应该用正则表达式做的事情。只需一次解析一个字符的字符串,跟踪开始/结束括号用于检测以分号结尾的C++;for&;while循环 在Python应用程序中,我需要编写一个与C++代码< > > >代码> >的正则表达式,而循环已经用一个半冒号终止了(;)。例如,它应该与以下内容匹配: for (int i = 0; i < 10; i++);,c++,python,regex,parsing,recursion,C++,Python,Regex,Parsing,Recursion,有人能建议对这个正则表达式进行改进吗?这对我来说太复杂了,我想不起来了。这是你真的不应该用正则表达式做的事情。只需一次解析一个字符的字符串,跟踪开始/结束括号 如果你只想找到这个,你肯定不需要一个完整的C++语法词典/解析器。如果你想练习的话,你可以编写一个简单的递归语法分析器,但是仅仅匹配括号就有点难了。这是一个使用错误工具的好例子。正则表达式不能很好地处理任意嵌套的子匹配。你应该做的是使用一个真正的词法分析器和语法分析器(C++的语法应该很容易找到),并且寻找意想不到的空循环体。 < P>我
如果你只想找到这个,你肯定不需要一个完整的C++语法词典/解析器。如果你想练习的话,你可以编写一个简单的递归语法分析器,但是仅仅匹配括号就有点难了。这是一个使用错误工具的好例子。正则表达式不能很好地处理任意嵌套的子匹配。你应该做的是使用一个真正的词法分析器和语法分析器(C++的语法应该很容易找到),并且寻找意想不到的空循环体。 < P>我甚至不注意父母的内容。 只需匹配以开头,以分号结尾的任何行即可:
^\t*for.+;$
除非您将
for
语句拆分为多行,否则这样做很好?Greg绝对正确。这种解析不能用正则表达式完成。我想有可能建立一些可怕的怪物,在很多情况下都能工作,但是你会遇到一些这样的东西
您确实需要使用更传统的解析技术。例如,编写一个递归解析器来完成您需要的工作非常简单 我不知道正则表达式是否能很好地处理这样的事情。试试这样的
line = line.Trim();
if(line.StartsWith("for") && line.EndsWith(";")){
//your code here
}
您可以编写一个小的、非常简单的例程来执行此操作,而无需使用正则表达式:
- 设置位置计数器
,使其指向pos
或for
的while
后面的开口支架前面李>
- 将开括号计数器
设置为openBr
0
- 现在,继续递增
,读取相应位置的字符,并在看到左括号时递增pos
,在看到右括号时递减。这将在开始时增加它一次,对于“openBr
”)中的第一个开口括号,对中间的一些括号再增加和减少一些,并在for(
括号关闭时将其设置回for
0
- 因此,当
再次为openBr
时停止0
- 将开括号计数器
停止位置是(…)的结束括号。现在可以检查后面是否有分号。另一种想法是忽略括号并将的
视为包含三个分号分隔值的构造:
for\s*\([^;]+;[^;]+;[^;]+\)\s*;
此选项即使在拆分多行时也有效(启用多行后),但假定(…;…;…)
的是唯一有效的构造,因此不适用于(x in y)
构造或其他偏差
还假设没有包含分号作为参数的函数,例如:
for ( var i = 0; i < ListLen('a;b;c',';') ; i++ );
for(var i=0;i
这种情况是否可能发生取决于您实际执行此操作的目的。请尝试使用此regexp
^\s*(for|while)\s*
\(
(?P<balanced>
[^()]*
|
(?P=balanced)
\)
\s*;\s
^\s*(用于| while)\s*
\(
(?P
[^()]*
|
(?P=平衡)
\)
\s*;\s
我移除了
\(\)
环绕(?p=balanced)
的包装,并将*
移动到any not paren序列的后面。我使用boost xpressive进行了这项工作,并重新检查了该网站()以刷新我的记忆。正如Frank所建议的,最好不要使用正则表达式。下面是(一个丑陋的)一行:
match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]
与他评论中提到的巨魔路线est相匹配:
orig_string = "for (int i = 0; i < 10; doSomethingTo(\"(\"));"
match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]
orig\u string=“for(inti=0;i<10;doSomethingTo(\”(\”);”
match_string=orig_string[orig_string.index(“”):len(orig_string)-orig_string[::-1]。index(“”))
返回(int i=0;i<10;doSomethingTo(“”)
它的工作原理是向前遍历字符串,直到它到达第一个打开的paren,然后向后遍历字符串,直到它到达第一个关闭的paren。然后它使用这两个索引对字符串进行切片。有点晚了,但我认为正则表达式不是执行此任务的合适工具 问题是,您会遇到边缘情况,这会给正则表达式增加额外的复杂性。提到:
for(int i=0;i<10;doSomethingTo(“”);
此字符串文字包含(不平衡!)括号,这会破坏逻辑。显然,您必须忽略字符串文字的内容。为此,必须考虑双引号。但字符串文字本身可以包含双引号。例如,请尝试以下操作:
for (int i = 0; i < 10; doSomethingTo("\"(\\"));
for(int i=0;i<10;doSomethingTo(\”(\”));
如果您使用正则表达式来解决这个问题,它将给您的模式增加更多的复杂性
我认为你最好用解析语言。例如,你可以使用一个语言识别工具,比如ANTLR。ANTLR是一个解析器生成器工具,它也可以生成一个。你必须提供一个定义目标语言的语法,在你的情况下C++。已经有很多语法在那里,所以你可以抓取。>
然后,您可以轻松地遍历解析器树,搜索空语句,如
,而或查找循环体。+1,严格来说,正则表达式根本不处理嵌套表达式。处理嵌套表达式的正则表达式已超越为上下文无关语法。我同意使用flex/yacc或类似的方法。但它是C++语法真的很容易找到吗?
for ( var i = 0; i < ListLen('a;b;c',';') ; i++ );
^\s*(for|while)\s*
\(
(?P<balanced>
[^()]*
|
(?P=balanced)
\)
\s*;\s
match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]
orig_string = "for (int i = 0; i < 10; doSomethingTo(\"(\"));"
match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]
for (int i = 0; i < 10; doSomethingTo("("));
for (int i = 0; i < 10; doSomethingTo("\"(\\"));