将匹配Java方法声明的正则表达式

我需要一个匹配java方法声明的正则表达式。 我想出了一个匹配方法声明的方法,但是它要求方法的左括号与声明位于同一行。 如果你有任何改善我的正则表达式的建议,或者只是有一个更好的,那么请提交一个答案。

这是我的正则表达式: "\w+ +\w+ *\(.*\) *\{"

对于那些不知道java方法是什么样子的人,我会提供一个基本的方法:

 int foo() { } 

Java方法有几个可选的部分,可以添加,但这些是一个方法保证唯一的部分。

更新:我目前的正则表达式是"\w+ +\w+ *\([^\)]*\) *\{"以防止Mike和adkom描述的情况。

你有没有考虑匹配实际可能的关键字? 如:

 (?:(?:public)|(?:private)|(?:static)|(?:protected)\s+)* 

正确匹配的可能性更大,但也可能使正则表达式更难读取。

 (public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;]) 

我认为上面的正则表达式可以匹配几乎所有可能的Java方法声明的组合,甚至包括泛型和数组的那些都是返回参数,原始作者提供的正则表达式不匹配。

我也需要这样一个正则表达式,并提出了这个解决方案:

 "((public|private|protected|static|final|native|synchronized|abstract|transient)+\\s)+[\\$_\\w\\<\\>\\[\\]]*\\s+[\\$_\\w]+\\([^\\)]*\\)?\\s*\\{?[^\\}]*\\}?" 

这个语法和Georgios Gousios的回答对构建正则表达式非常有用。

看完其他答案后,我想到了:

 #permission ^[ \t]*(?:(?:public|protected|private)\s+)? #keywords (?:(static|final|native|synchronized|abstract|threadsafe|transient|{#insert zJRgx123GenericsNotInGroup})\s+){0,} #return type #If return type is "return" then it's actually a 'return funcName();' line. Ignore. (?!return) \b([\w.]+)\b(?:|{#insert zJRgx123GenericsNotInGroup})((?:\[\]){0,})\s+ #function name \b\w+\b\s* #parameters \( #one \s*(?:\b([\w.]+)\b(?:|{#insert zJRgx123GenericsNotInGroup})((?:\[\]){0,})(\.\.\.)?\s+(\w+)\b(?![>\[]) #two and up \(\s*(?:,\s+\b([\w.]+)\b(?:|{#insert zJRgx123GenericsNotInGroup})((?:\[\]){0,})(\.\.\.)?\s+(\w+)\b(?![>\[])\s*){0,})?\s* \) #post parameters (?:\s*throws [\w.]+(\s*,\s*[\w.]+))? #close-curly (concrete) or semi-colon (abstract) \s*(?:\{|;)[ \t]*$ 

其中{#insert zJRgx123GenericsNotInGroup}等于

 `(?:<[?\w\[\] ,.&]+>)|(?:<[^<]*<[?\w\[\] ,.&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,.&]+>[^>]*>[^>]*>)` 

限制:

  • 任何参数都可以有省略号:“…”(Java只允许最后一个)
  • 最多三层嵌套泛型:( <...<...<...>...>...>好, <...<...<...<...>...>...>...> bad)。 泛型中的语法可能非常虚假,对于这个正则表达式看起来还是可以的。
  • 类型和(可选)开放泛型之间不需要空格“<”
  • 识别内部类,但不阻止彼此相邻的两个点,例如Class …. InnerClass

下面是原始的PhraseExpress代码(第1行的自动文本和描述,第2行的主体)。 调用{#insert zJRgxJavaFuncSigThrSemicOrOpnCrly} ,你会得到这个:

 ^[ \t]*(?:(?:public|protected|private)\s+)?(?:(static|final|native|synchronized|abstract|threadsafe|transient|(?:<[?\w\[\] ,&]+>)|(?:<[^<]*<[?\w\[\] ,&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,&]+>[^>]*>[^>]*>))\s+){0,}(?!return)\b([\w.]+)\b(?:|(?:<[?\w\[\] ,&]+>)|(?:<[^<]*<[?\w\[\] ,&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,&]+>[^>]*>[^>]*>))((?:\[\]){0,})\s+\b\w+\b\s*\(\s*(?:\b([\w.]+)\b(?:|(?:<[?\w\[\] ,&]+>)|(?:<[^<]*<[?\w\[\] ,&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,&]+>[^>]*>[^>]*>))((?:\[\]){0,})(\.\.\.)?\s+(\w+)\b(?![>\[])\s*(?:,\s+\b([\w.]+)\b(?:|(?:<[?\w\[\] ,&]+>)|(?:<[^<]*<[?\w\[\] ,&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,&]+>[^>]*>[^>]*>))((?:\[\]){0,})(\.\.\.)?\s+(\w+)\b(?![>\[])\s*){0,})?\s*\)(?:\s*throws [\w.]+(\s*,\s*[\w.]+))?\s*(?:\{|;)[ \t]*$ 

原始码:

 zJRgx123GenericsNotInGroup -- To precede return-type (?:<[?\w\[\] ,.&]+>)|(?:<[^<]*<[?\w\[\] ,.&]+>[^>]*>)|(?:<[^<]*<[^<]*<[?\w\[\] ,.&]+>[^>]*>[^>]*>) zJRgx123GenericsNotInGroup zJRgx0OrMoreParams \s*(?:{#insert zJRgxParamTypeName}\s*(?:,\s+{#insert zJRgxParamTypeName}\s*){0,})?\s* zJRgx0OrMoreParams zJRgxJavaFuncNmThrClsPrn_M_fnm -- Needs zvFOBJ_NAME (?<=\s)\b{#insert zvFOBJ_NAME}{#insert zzJRgxPostFuncNmThrClsPrn} zJRgxJavaFuncNmThrClsPrn_M_fnm zJRgxJavaFuncSigThrSemicOrOpnCrly -(**)- {#insert zzJRgxJavaFuncSigPreFuncName}\w+{#insert zzJRgxJavaFuncSigPostFuncName} zJRgxJavaFuncSigThrSemicOrOpnCrly zJRgxJavaFuncSigThrSemicOrOpnCrly_M_fnm -- Needs zvFOBJ_NAME {#insert zzJRgxJavaFuncSigPreFuncName}{#insert zvFOBJ_NAME}{#insert zzJRgxJavaFuncSigPostFuncName} zJRgxJavaFuncSigThrSemicOrOpnCrly_M_fnm zJRgxOptKeywordsBtwScopeAndRetType (?:(static|final|native|synchronized|abstract|threadsafe|transient|{#insert zJRgx123GenericsNotInGroup})\s+){0,} zJRgxOptKeywordsBtwScopeAndRetType zJRgxOptionalPubProtPriv (?:(?:public|protected|private)\s+)? zJRgxOptionalPubProtPriv zJRgxParamTypeName -(**)- Ends w/ '\b(?![>\[])' to NOT find <? 'extends XClass'> or ...[]> (*Original: zJRgxParamTypeName, Needed by: zJRgxParamTypeName[4FQPTV,ForDel[NmsOnly,Types]]*){#insert zJRgxTypeW0123GenericsArry}(\.\.\.)?\s+(\w+)\b(?![>\[]) zJRgxParamTypeName zJRgxTypeW0123GenericsArry -- Grp1=Type, Grp2='[]', if any \b([\w.]+)\b(?:|{#insert zJRgx123GenericsNotInGroup})((?:\[\]){0,}) zJRgxTypeW0123GenericsArry zvTTL_PRMS_stL1c {#insert zCutL1c}{#SETPHRASE -description zvTTL_PRMS -content {#INSERTCLIPBOARD} -autotext zvTTL_PRMS -folder ctvv_folder} zvTTL_PRMS_stL1c zvTTL_PRMS_stL1cSvRstrCB {#insert zvCB_CONTENTS_stCB}{#insert zvTTL_PRMS_stL1c}{#insert zSetCBToCB_CONTENTS} zvTTL_PRMS_stL1cSvRstrCB zvTTL_PRMS_stPrompt {#SETPHRASE -description zvTTL_PRMS -content {#INPUT -head How many parameters? -single} -autotext zvTTL_PRMS -folder ctvv_folder} zvTTL_PRMS_stPrompt zzJRgxJavaFuncNmThrClsPrn_M_fnmTtlp -- Needs zvFOBJ_NAME, zvTTL_PRMS (?<=[ \t])\b{#insert zvFOBJ_NAME}\b\s*\(\s*{#insert {#COND -if {#insert zvTTL_PRMS} = 0 -then z1slp -else zzParamsGT0_M_ttlp}}\) zzJRgxJavaFuncNmThrClsPrn_M_fnmTtlp zzJRgxJavaFuncSigPostFuncName {#insert zzJRgxPostFuncNmThrClsPrn}(?:\s*throws \b(?:[\w.]+)\b(\s*,\s*\b(?:[\w.]+)\b))?\s*(?:\{|;)[ \t]*$ zzJRgxJavaFuncSigPostFuncName zzJRgxJavaFuncSigPreFuncName (*If a type has generics, there may be no spaces between it and the first open '<', also requires generics with three nestings at the most (<...<...<...>...>...> okay, <...<...<...<...>...>...>...> not)*)^[ \t]*{#insert zJRgxOptionalPubProtPriv}{#insert zJRgxOptKeywordsBtwScopeAndRetType}(*To prevent 'return funcName();' from being recognized:*)(?!return){#insert zJRgxTypeW0123GenericsArry}\s+\b zzJRgxJavaFuncSigPreFuncName zzJRgxPostFuncNmThrClsPrn \b\s*\({#insert zJRgx0OrMoreParams}\) zzJRgxPostFuncNmThrClsPrn zzParamsGT0_M_ttlp -- Needs zvTTL_PRMS {#insert zJRgxParamTypeName}\s*{#insert {#COND -if {#insert zvTTL_PRMS} = 1 -then z1slp -else zzParamsGT1_M_ttlp}} zzParamsGT0_M_ttlp zzParamsGT1_M_ttlp {#LOOP ,\s+{#insert zJRgxParamTypeName}\s* -count {#CALC {#insert zvTTL_PRMS} - 1 -round 0 -thousands none}} zzParamsGT1_M_ttlp 

我很确定默认情况下Java的正则表达式引擎是贪婪的,这意味着"\w+ +\w+ *\(.*\) *\{"将永远不会匹配,因为圆括号内的。 我建议你用[^)替换.* ,这样你将选择所有非关闭字符。

注意: Mike Stone在评论中纠正了我,因为大多数人并没有真正打开评论(我知道我经常没有注意到他们):

贪婪并不意味着它永远不会匹配…但是,如果有更多的parens满足其余的正则表达式,它会吃parens …所以例如“public void foo(int arg){if(test){ System.exit(0);}}“将不能正确匹配…

我想出了这个:

 \b\w*\s*\w*\(.*?\)\s*\{[\x21-\x7E\s]*\} 

我对PHP函数进行了测试,但它应该工作得一样,这是我使用的代码片段:

 function getProfilePic($url) { if(@open_image($url) !== FALSE) { @imagepng($image, 'images/profiles/' . $_SESSION['id'] . '.png'); @imagedestroy($image); return TRUE; } else { return FALSE; } } 

更多信息:

 Options: case insensitive Assert position at a word boundary «\b» Match a single character that is a “word character” (letters, digits, etc.) «\w*» Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s*» Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» Match a single character that is a “word character” (letters, digits, etc.) «\w*» Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» Match the character “(” literally «\(» Match any single character that is not a line break character «.*?» Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?» Match the character “)” literally «\)» Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.) «\s*» Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» Match the character “{” literally «\{» Match a single character present in the list below «[\x21-\x7E\s]*» Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» A character in the range between ASCII character 0x21 (33 decimal) and ASCII character 0x7E (126 decimal) «\x21-\x7E» A whitespace character (spaces, tabs, line breaks, etc.) «\s» Match the character “}” literally «\}» Created with RegexBuddy 

一个提示:

如果你要在Perl中编写正则表达式,请使用“xms”选项,这样你就可以留下空间并记录正则表达式。 例如,你可以写一个正则表达式:

  m{\w+ \s+ #return type \w+ \s* #function name [(] [^)]* [)] #params \s* [{] #open paren }xms 

其中一个选项(think x)允许在正则表达式中使用#注释。 也可以使用\ s代替“”。 \ s代表任何“空白”字符。 所以选项卡也将匹配 – 这是你想要的。 在Perl中,您不需要使用//,可以使用{}或<>或| |。

不知道其他语言是否有这个能力。 如果他们这样做,那么请使用它们。

我建立了一个vim正则表达式来完成基于Georgios Gousios的答案的ctrlp / funky 。

  let regex = '\v^\s+' " preamble let regex .= '%(<\w+>\s+){0,3}' " visibility, static, final let regex .= '%(\w|[<>[\]])+\s+' " return type let regex .= '\w+\s*' " method name let regex .= '\([^\)]*\)' " method parameters let regex .= '%(\w|\s|\{)+$' " postamble 

我猜这在Java中看起来像这样:

 ^\s+(?:<\w+>\s+){0,3}(?:[\w\<\>\[\]])+\s+\w+\s*\([^\)]*\)(?:\w|\s|\{)+$ 

这是一个更具体的用例,但它是如此简单,我相信它值得分享。 我这样做是为了找到'公共静态无效'的方法,即播放控制器的行动,我做了从Windows / Cygwin的命令行,使用grep; 请参阅: https : //stackoverflow.com/a/7167115/34806

 cat Foobar.java | grep -Pzo '(?s)public static void.*?\)\s+{' 

我输出的最后两个条目如下:

 public static void activeWorkEventStations (String type, String symbol, String section, String day, String priority, @As("yyyy-MM-dd") Date scheduleDepartureDate) { public static void getActiveScheduleChangeLogs(String type, String symbol, String section, String day, String priority, @As("yyyy-MM-dd") Date scheduleDepartureDate) { 

我发现seba229的答案很有用,它抓住了大部分情况,但不是以下情况,

 public <T> T name(final Class<T> x, final T y) 

这个正则表达式也会捕获这个。

 ((public|private|protected|static|final|native|synchronized|abstract|transient)+\s)+[\$_\w\<\>\w\s\[\]]*\s+[\$_\w]+\([^\)]*\)?\s* 

希望这可以帮助。

 (public|private|static|protected) ([A-Za-z0-9<>.]+) ([A-Za-z0-9]+)\( 

另外,这里有一个你可以在IntelliJ中使用的替换序列

 $1 $2 $3( 

我这样使用它:

 $1 $2 aaa$3( 

当将Java文件转换为Kotlin以防止以“get”开头的函数自动变成变量时。 不能使用“默认”访问级别,但我自己并没有那么多。