[英]what is Regular expression for detecting a for loop and while loop in Java code
什么是正则表达式,用于检测a是否为loo,另一个是用于检测while循环。 想要检测for(--;--;--)
while (--comparison operator --)
和while (--comparison operator --)
构造。
使用正则表达式不能可靠地做到这一点。 您需要使用适当的解析器来解析代码。
在Java中使用\\s
来检测Java代码中的空格的人们正在犯至少一个,甚至几个错误。
首先,Java编译器本身对空格的想法与Java中\\s
匹配方式不一致。 您可以通过\\p{JavaWhitespace}
属性访问Java Character.isWhitespace()
。
其次,Java不允许\\s
匹配Unicode空格; 按照Java Pattern
类中的实现, \\s
仅与ASCII空格匹配。 实际上,Java不支持与Unicode空格相对应的任何属性。
下表显示了一些问题区域:
000A 0085 00A0 2029
J P J P J P J P
\s 1 1 0 1 0 1 0 1
\pZ 0 0 0 0 1 1 1 1
\p{Zs} 0 0 0 0 1 1 0 0
\p{Space} 1 1 0 1 0 1 0 1
\p{Blank} 0 0 0 0 0 1 0 0
\p{Whitespace} - 1 - 1 - 1 - 1
\p{javaWhitespace} 1 - 0 - 0 - 1 -
\p{javaSpaceChar} 0 - 0 - 1 - 1 -
您在x轴上看到的是四个不同的代码点:
U+000A: LINE FEED (LF)
U+0085: NEXT LINE (NEL)
U+00A0: NO-BREAK SPACE
U+2029: PARAGRAPH SEPARATOR
y轴具有八个不同的正则表达式测试,主要是属性。 对于每个代码点,Java都有一个J-results列,而Perl或任何其他基于PCRE的正则表达式引擎都有一个P-results列。
这是个大问题。 Java只是一团糟,根据现有实践以及根据Unicode,给出的答案都是“错误的”。 另外,Java甚至都不允许您访问真正的Unicode属性。 为了记录,这些是带有Unicode空白属性的代码点:
% unichars '\pP{Whitespace}'
0009 CHARACTER TABULATION
000A LINE FEED (LF)
000B LINE TABULATION
000C FORM FEED (FF)
000D CARRIAGE RETURN (CR)
0020 SPACE
0085 NEXT LINE (NEL)
00A0 NO-BREAK SPACE
1680 OGHAM SPACE MARK
180E MONGOLIAN VOWEL SEPARATOR
2000 EN QUAD
2001 EM QUAD
2002 EN SPACE
2003 EM SPACE
2004 THREE-PER-EM SPACE
2005 FOUR-PER-EM SPACE
2006 SIX-PER-EM SPACE
2007 FIGURE SPACE
2008 PUNCTUATION SPACE
2009 THIN SPACE
200A HAIR SPACE
2028 LINE SEPARATOR
2029 PARAGRAPH SEPARATOR
202F NARROW NO-BREAK SPACE
205F MEDIUM MATHEMATICAL SPACE
3000 IDEOGRAPHIC SPACE
如果你想,随时抢单字符程序和玩它和它的配套程序, uniprops和uninames 。 我还没有添加仅Java的属性,但是我打算这样做。 像上面描述的那样,有太多令人讨厌的惊喜。
对于\\p{javaJavaIdentifierStart}
,您相信Java中有一个\\p{javaJavaIdentifierStart}
属性吗? 我不骗你 但是您不会相信编译器实际上允许您在标识符中使用的字符。 真的你不会。 有人没有注意。 再次。 :(
您可以使用现代(PCRE风格)正则表达式解析几乎所有内容。 但是, 正确地解析某些事物通常在病理上是困难的。 构建一个小巧的正则表达式以仅匹配某些简单格式化的for循环很容易:
for\s*\([^;]*?;[^;]*?;[^)]*?\)
但是,当您遇到这种情况时会发生什么?
int i = 0;
for(
String s = "for(0;1;2)";
s.indexOf(String.valueOf(i)) != -1;
i++ // increment the i variable ;-)
)
如果需要100%的可靠性,最好使用成熟的专用Java解析器。 java.net文章“使用Java 6 API进行源代码分析”提供了一种可靠地解析Java源代码的方法的起点。
回复塔兹的评论:
我用
.*for(.*;.*;.*).*
做到了.*for(.*;.*;.*).*
这可能是什么问题?
假设您要匹配的所有for循环都具有:
我认为您的模式应该可以。 您可能需要在for
和左括号之间留出空格:
.*for\s*(.*;.*;.*).*
但是,正如tchrist在回答此问题时指出的那样, \\s*
并不是在Java源代码中允许空格的完美正确方法,因为Java源代码支持\\s
不允许的Unicode空格类型。 同样,如果您需要100%的可靠性,那么完整的Java源代码解析器可能是一个更好的选择。
确保您关闭(或不打开)在您的解析器(如“点匹配换行符”选项DOTALL或单线 )。 否则,您的正则表达式可能会跨多行匹配,这很可能导致您的正则表达式不正确匹配。
for ?\(.*?;.*?;.*?\)
while ?\(.+?\)
如果代码会变得非常复杂(除了说:此循环是否发生在代码中的任何地方),请改用解析器。
我们为什么需要这些? 这里。 我确实需要检测到while循环中有一个比较运算符
如果我要离开? 则它将匹配for ( for(this;that;theother)
我更新了while循环以使用+
我认为合资公司给出的正则表达式包含额外的问号。
这是我的版本:
for\s*\([^;]*;[^;]*;[^)]*\)
while\\s*\\(.*?\\)
是正确的,但
while\\s*\\([^)]*\\)
应该更快。
For循环最容易检测到:
for *\(.*;.*;.*)
虽然循环有点棘手,但是有两种方法可以做到。 如果要使用上面指定的格式,则应该可以使用:
while *\(.*(<|>|<=|>=|==|!=).*\)
但是,这不会检测到何时条件取决于变量的布尔值,也不取决于方法的布尔结果,因此此版本会更简单一些,并且匹配更多:
while *\(.*\)
正则表达式只能解析正则(Ch-3)语言。 Java不是常规语言,它至少是上下文无关的(Ch-2),甚至是上下文敏感的(Ch-1)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.