什么是用于检测for循环的正则表达式和用于检测while循环的另一个正则表达式。
想要检测for(--;--;--)
和while (--comparison operator --)
结构。
答案 0 :(得分:11)
使用正则表达式无法可靠地执行此操作。您需要使用适当的解析器解析代码。
答案 1 :(得分:5)
在Java中使用\s
来检测Java代码中的空格的人们至少会犯一个甚至几个错误。
首先,Java编译器本身的空白概念与Java中\s
匹配的内容不一致。您可以通过Character.isWhitespace()
属性访问Java \p{JavaWhitespace}
。
其次,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结果列,也有Perl的P结果列或任何其他基于PCRE的正则表达式引擎。
这是一个大问题。 Java只是搞砸了,根据现有的做法和Unicode也给出了“错误”的答案。 Plus 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
如果您愿意,可以随时抓住unichars program并使用它及其配套计划uniprops和uninames。我还没有添加仅Java属性,但我打算这样做。有太多令人讨厌的惊喜,如上所述。
对于踢和笑,你会相信Java中有\p{javaJavaIdentifierStart}
属性吗?我没骗你。但你不会相信编译器实际允许你在标识符中使用的字符;真的你不会。有人没有注意。再次。 :(
答案 2 :(得分:4)
您可以使用现代(PCRE样式)正则表达式解析几乎所有内容。但是,解析某些事情正确通常在病理上很困难。很容易构建一个小的,简洁的正则表达式来匹配只有某些类型的简单格式化的循环:
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文章Source Code Analysis Using Java 6 APIs为一种可靠地解析Java源代码的方法提供了一个起点。
回复Taz的评论:
我用
.*for(.*;.*;.*).*
做了这件事可能有什么问题?
假设您要匹配的所有for循环都包含:
我认为你的模式应该没问题。您可能希望允许for
和左括号之间的空格:
.*for\s*(.*;.*;.*).*
然而,正如tchrist在his answer中指出的那样,\s*
并不是一种在Java源代码中允许空格的完全正确的方法,因为Java源代码支持{{{ 1}}不允许。同样,如果您需要100%的可靠性,完整的Java源代码解析器可能是更好的选择。
确保您在解析器中关闭(或不启用)“点匹配换行符”选项(例如DOTALL或Singleline)。否则你的正则表达式可以匹配多行,这可能会导致你的正则表达式不正确匹配。
答案 3 :(得分:0)
for ?\(.*?;.*?;.*?\)
while ?\(.+?\)
如果代码会变得非常复杂(除了说:这个循环是否出现在代码中的任何地方)请使用解析器。
为什么我们需要这些?这里。我确实需要检测while循环中是否存在比较运算符
如果我要离开?那么它会匹配for ( for(this;that;theother)
我更新了while循环以使用+
答案 4 :(得分:0)
我认为JV给出的正则表达式包含额外的问号。
这是我的版本:
for\s*\([^;]*;[^;]*;[^)]*\)
while\s*\(.*?\)
是正确的,但
while\s*\([^)]*\)
应该更快。
答案 5 :(得分:0)
For循环是最容易检测的:
for *\(.*;.*;.*)
虽然循环有点棘手,但有两种方法可以做到。 如果您想使用上面指定的格式,这应该有效:
while *\(.*(<|>|<=|>=|==|!=).*\)
但是,这不会检测依赖于变量的布尔值的条件,也不会检测方法的布尔结果,因此这个版本会更简单并且更匹配:
while *\(.*\)
答案 6 :(得分:0)
正则表达式只能解析常规(Ch-3)语言。 Java不是常规语言,至少无上下文(Ch-2),甚至可能是上下文敏感的(Ch-1)。