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

Tas*_*han 1 java regex

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

Dav*_*nan 11

使用正则表达式无法可靠地执行此操作.您需要使用适当的解析器解析代码.

  • 举个例子,我推荐来自http://code.google.com/p/javaparser的JavaParser,这是一个解析Java代码的Java解析器.有趣/相关的部分是java_1_5.jj文件,其中包含Java语言的标记/语法(部分使用正则表达式定义). (2认同)

Mik*_*ark 5

您可以使用现代(PCRE 风格)正则表达式解析几乎所有内容。然而,正确解析某些事物通常在病理上是困难的。很容易构建一个小的、简洁的正则表达式来匹配某些类型的简单格式化的 for 循环:

for\s*\([^;]*?;[^;]*?;[^)]*?\)
Run Code Online (Sandbox Code Playgroud)

但是当你遇到这样的事情时会发生什么?

int i = 0;
for(
        String s = "for(0;1;2)";
        s.indexOf(String.valueOf(i)) != -1;
        i++ // increment the i variable ;-)
   )
Run Code Online (Sandbox Code Playgroud)

如果您需要 100% 的可靠性,最好使用成熟的专用 Java 解析器。java.net 文章使用 Java 6 API 进行源代码分析提供了一种对 Java 源代码进行可靠解析的方法的起点。


回复 Taz 的评论:

我这样做有.*for(.*;.*;.*).*什么问题吗?

假设您要匹配的所有 for 循环具有:

  1. 他们没有换行,
  2. 没有嵌入/尾随评论
  3. 其中没有“字符串”或“字符”字面量

我觉得你的模式应该没问题。您可能希望在for和 左括号之间留有空格:

.*for\s*(.*;.*;.*).*
Run Code Online (Sandbox Code Playgroud)

然而,正如 tchrist 在对这个问题的回答中指出的那样,\s*在 Java 源代码中允许空白并不是一种完全正确的方法,因为 Java 源代码支持\s不允许的 Unicode 空白类型。同样,如果您需要 100% 的可靠性,完整的 Java 源代码解析器可能是更好的选择。

请确保您关闭(或不打开)中的“点匹配的换行符”选项解析器(例如DOTALL单线)。否则您的正则表达式可能会匹配多行,这可能会导致您的正则表达式匹配不正确。


tch*_*ist 5

\s在Java 中使用Java代码检测空格的人们至少会犯一个甚至几个错误.

首先,Java编译器对空白空间的想法\s与Java中的匹配不一致.您可以Character.isWhitespace()通过该\p{JavaWhitespace}属性访问Java .

其次,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  -
Run Code Online (Sandbox Code Playgroud)

您在x轴上看到的是四个不同的代码点:

U+000A: LINE FEED (LF)
U+0085: NEXT LINE (NEL)
U+00A0: NO-BREAK SPACE
U+2029: PARAGRAPH SEPARATOR
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如果你愿意,可以随意获取unichars程序并使用它和它的伴侣程序, unipropsuninames.我还没有添加仅Java属性,但我打算这样做.有太多令人讨厌的惊喜,如上所述.

对于踢和笑,你会相信\p{javaJavaIdentifierStart}Java中有一个属性吗?我没骗你.但你不会相信编译器实际允许你在标识符中使用的字符; 真的你不会.有人没有注意.再次.:(