【问题标题】:Regex that Will Match a Java Method Declaration将匹配 Java 方法声明的正则表达式
【发布时间】:2010-09-09 06:40:36
【问题描述】:

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

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

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

int foo()
{

}

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

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

【问题讨论】:

  • 我不知道Java方法声明是什么样子介意提供一个例子吗?

标签: java regex methods


【解决方案1】:
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])

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

【讨论】:

  • 我认为可以。它也将排除构造函数,这很好:-)
  • 开头的\s 是干什么用的?为什么某些东西会以两个空格开头?除非缩进恰到好处,否则阻止它匹配包范围。
  • @seba229 的回答包含了一些您没有的关键字
  • 您在该列表中缺少native
  • @Shane 您的正则表达式无法匹配方法名称的最后一个字符。 (public|protected|private|static|\s) +[\w\&lt;\&gt;\[\],\s]+\s+(\w+) *\([^\)]*\) *(\{?|[^;]) 为我工作。
【解决方案2】:

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

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

grammar 和 Georgios Gousios 的回答对于构建正则表达式很有用。

编辑:考虑了 tharindu_DG 的反馈,使组不被捕获,改进了格式。

【讨论】:

【解决方案3】:

查看其他答案后,这是我想出的:

#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 只允许最后一个)
  • 最多三层嵌套泛型:(&lt;...&lt;...&lt;...&gt;...&gt;...&gt;好的,&lt;...&lt;...&lt;...&lt;...&gt;...&gt;...&gt;...&gt;不好)。泛型中的语法可能非常虚假,但对于这个正则表达式来说似乎还可以。
  • 类型及其(可选)开头的泛型'之间不需要空格
  • 识别内部类,但不阻止相邻的两个点,例如 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

【讨论】:

  • 必须向 RegexBuddy 提供帮助以帮助我解决此问题:regexbuddy.com
  • 令人印象深刻的彻底答案!我在我的 .gitconfig 中尝试过,并得到一个“致命:错误的配置行”错误。我尝试转义反斜杠,然后向上移动到“致命:无效的正则表达式以查找大块标头”错误。唔。也许我需要了解 .gitconfig 中需要转义的内容。
  • 在浏览了需要转义的 git-config 文档后,我用双引号将整个内容括起来,这样分号就不会终止该值。仍然出现“致命:查找大块标头的正则表达式无效”错误。
【解决方案4】:

您是否考虑过匹配实际可能的关键字?如:

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

它可能更有可能正确匹配,尽管它也可能使正则表达式更难阅读......

【讨论】:

  • 该正则表达式最终匹配​​了我拥有的所有方法的签名,例如 System.out.println() 而不仅仅是方法的声明。
  • 匹配静态变量,不匹配包作用域方法。
  • 这是一个基于上述内容的更完整的正则表达式。 IDE 替换 "$1 $2 $3(" 和 regex (unquoted) (public|private|static|protected) ([A-Za-z]+) ([A-Za-z0-9]+)(
  • 没有修饰符的方法呢?
【解决方案5】:

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

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

贪婪并不意味着它永远不会匹配......但是如果在满足正则表达式的其余部分之后有更多的括号,它会吃掉括号......例如“public void foo(int arg){ if( test) { System.exit(0); } }" 将无法正确匹配...

【讨论】:

  • 贪婪并不意味着它永远不会匹配......但是如果在满足正则表达式的其余部分之后有更多的括号,它会吃掉括号......例如“public void foo(int arg) { if (test) { System.exit(0); } }" 将无法正确匹配...
【解决方案6】:

我想出了这个:

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

我针对 PHP 函数对其进行了测试,但它应该可以正常工作,这是我使用的代码的 sn-p:

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

【讨论】:

    【解决方案7】:

    (public|private|static|protected|abstract|native|synchronized) +([a-zA-Z0-9&lt;&gt;._?, ]+) +([a-zA-Z0-9_]+) *\\([a-zA-Z0-9&lt;&gt;\\[\\]._?, \n]*\\) *([a-zA-Z0-9_ ,\n]*) *\\{

    上面的 Regex 将检测所有可能的 java 方法定义。在大量源代码文件上进行了测试。要包含构造函数,请使用以下正则表达式:

    (public|private|static|protected|abstract|native|synchronized) +([a-zA-Z0-9&lt;&gt;._?, ]*) +([a-zA-Z0-9_]+) *\\([a-zA-Z0-9&lt;&gt;\\[\\]._?, \n]*\\) *([a-zA-Z0-9_ ,\n]*) *\\{

    【讨论】:

      【解决方案8】:

      提示:

      如果您打算在 Perl 中编写正则表达式,请使用“xms”选项,以便您可以留出空格并记录正则表达式。例如,您可以编写如下正则表达式:

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

      其中一个选项(想想 x)允许在正则表达式中使用 # cmets。也使用 \s 而不是“”。 \s 代表任何“空白”字符。所以标签也会匹配——这就是你想要的。在 Perl 中你不需要使用 //,你可以使用 { } 或 或 | |.

      不确定其他语言是否有这种能力。如果有,请使用它们。

      【讨论】:

      • java中有类似的选项吗?
      【解决方案9】:

      这是一个更具体的用例,但它非常简单,我相信它值得分享。我这样做是为了找到“公共静态无效”方法,即播放控制器操作,我是从 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) {
      

      【讨论】:

        【解决方案10】:

        从 git 2.19.0 开始,built-in regexp for Java 现在似乎运行良好,因此可能不需要自己提供。

        "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
        "^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$"
        

        (第一行似乎是为了过滤掉类似于方法声明但不是的行。)

        【讨论】:

          【解决方案11】:

          这将选择方法的名称而不是整行。

          (?<=public static void )\w+|(?<=private static void )\w+|(?<=protected static void )\w+|(?<=public void )\w+|(?<=private void )\w+|(?<=protected void )\w+|(?<=public final void)\w+|(?<=private final void)\w+|(?<=protected final void)\w+|(?<=private void )\w+|(?<=protected void )\w+|(?<=public static final void )\w+|(?<=private static final void )\w+|(?<=public final static void )\w+|(?<=protected final static void )\\w+|(?<=private final static void )\w+|(?<=protected final static void )\w+|(?<=void )\w+|(?<=private static )\w+
          

          【讨论】:

            【解决方案12】:

            我根据 Georgios Gousios 的回答为 ctrlp/funky 构建了一个 vim 正则表达式。

                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|\{)+$
            

            【讨论】:

              【解决方案13】:

              我发现 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*
              

              希望这会有所帮助。

              【讨论】:

                【解决方案14】:
                (public|private|static|protected) ([A-Za-z0-9<>.]+) ([A-Za-z0-9]+)\(
                

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

                $1 $2 $3(
                

                我是这样使用的:

                $1 $2 aaa$3(
                

                在将 Java 文件转换为 Kotlin 以防止以“get”开头的函数自动转换为变量时。不适用于“默认”访问级别,但我自己用的不多。

                【讨论】:

                  猜你喜欢
                  • 2019-08-09
                  • 1970-01-01
                  • 2011-03-01
                  • 2018-05-03
                  • 1970-01-01
                  • 2011-03-30
                  • 2011-05-26
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多