簡體   English   中英

什么是用於檢測Java代碼中的for循環和while循環的正則表達式

[英]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

如果你想,隨時搶單字符程序和玩它和它的配套程序, unipropsuninames 我還沒有添加僅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循環都具有:

  1. 他們沒有換行符,
  2. 沒有嵌入/跟蹤評論
  3. 其中沒有“字符串”或“ c”字符文字

我認為您的模式應該可以。 您可能需要在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM