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