什么是正则表达式,用于检测Java代码中的for循环和while循环

时间:2010-11-21 19:19:23

标签: java regex

什么是用于检测for循环的正则表达式和用于检测while循环的另一个正则表达式。 想要检测for(--;--;--)while (--comparison operator --)结构。

7 个答案:

答案 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并使用它及其配套计划unipropsuninames。我还没有添加仅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循环都包含:

  1. 其中没有换行符,
  2. 没有嵌入/尾随评论
  3. 其中没有“字符串”或“c”字符文字
  4. 我认为你的模式应该没问题。您可能希望允许for和左括号之间的空格:

    .*for\s*(.*;.*;.*).*
    

    然而,正如tchrist在his answer中指出的那样,\s*并不是一种在Java源代码中允许空格的完全正确的方法,因为Java源代码支持{{{ 1}}不允许。同样,如果您需要100%的可靠性,完整的Java源代码解析器可能是更好的选择。

    确保您在解析器中关闭(或不启用)“点匹配换行符”选项(例如DOTALLSingleline)。否则你的正则表达式可以匹配多行,这可能会导致你的正则表达式不正确匹配。

答案 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)。