提问人:Anton 提问时间:9/16/2008 最后编辑:Anton 更新时间:10/17/2023 访问量:32748
将匹配 Java 方法声明的正则表达式
Regex that Will Match a Java Method Declaration
问:
我需要一个与 java 方法声明匹配的正则表达式。我想出了一个与方法声明相匹配的方法,但它要求方法的左括号与声明在同一行上。如果您有任何建议来改进我的正则表达式或只是有更好的正则表达式,请提交答案。
这是我的正则表达式:"\w+ +\w+ *\(.*\) *\{"
对于那些不知道 java 方法是什么样子的人,我将提供一个基本的方法:
int foo()
{
}
Java 方法中有几个可选部分也可以添加,但这些是方法保证具有的唯一部分。
更新:
我目前的正则表达式是为了防止 Mike 和 adkom 描述的情况。"\w+ +\w+ *\([^\)]*\) *\{"
答:
您是否考虑过匹配实际可能的关键字?如:
(?:(?:public)|(?:private)|(?:static)|(?:protected)\s+)*
它可能更有可能正确匹配,尽管它也可能使正则表达式更难阅读......
评论
我很确定 Java 的正则表达式引擎默认是贪婪的,这意味着它永远不会匹配,因为括号内的正则表达式会在开场白之后吃掉所有东西。我建议您将 替换为 [^)],这样您将选择所有非闭合字符。"\w+ +\w+ *\(.*\) *\{"
.*
.*
注意:迈克·斯通(Mike Stone)在评论中纠正了我,由于大多数人并没有真正打开评论(我知道我经常没有注意到它们):
贪婪并不意味着它永远不会匹配......但是,如果之后有更多的正则表达式来满足其余的正则表达式,它就会吃掉 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
其中一个选项(想想 x)允许在正则表达式中使用 # 注释。也使用 \s 而不是 “ ”。\s 代表任何“空白”字符。所以标签页也会匹配 -- 这是你想要的。在 Perl 中,你不需要使用 / /,你可以使用 { } 或 < > 或 | |。
不确定其他语言是否具有这种能力。如果它们有,那么请使用它们。
评论
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
我认为上面的正则表达式几乎可以匹配所有可能的 Java 方法声明组合,甚至包括泛型和数组在内的那些都是返回参数,而原作者提供的正则表达式并不匹配。
评论
\s
native
(public|protected|private|static|\s) +[\w\<\>\[\],\s]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
我根据 Georgios Gousios 的回答构建了一个 vim 正则表达式来为 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|\{)+$
我也需要这样一个正则表达式,并提出了这个解决方案:
(?:(?:public|private|protected|static|final|native|synchronized|abstract|transient)+\s+)+[$_\w<>\[\]\s]*\s+[\$_\w]+\([^\)]*\)?\s*\{?[^\}]*\}?
这个语法和 Georgios Gousios 的答案对于构建正则表达式很有用。
编辑:考虑了tharindu_DG的反馈,使组不捕获,改进了格式。
评论
在浏览了其他答案后,我想出了以下结论:
#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\[\] ,.&]+>[^>]*>[^>]*>)`
局限性:
- ANY 参数可以有一个省略号:“...”(Java 只允许 last)
- 最多三个级别的嵌套泛型:(好的,不好的)。泛型中的语法可能非常虚假,但对于这个正则表达式来说似乎还可以。
<...<...<...>...>...>
<...<...<...<...>...>...>...>
- 类型及其(可选)开始泛型“<”之间不需要空格
- 识别内部类,但不阻止两个点彼此相邻,例如 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
评论
这是针对更具体的用例,但它要简单得多,我相信它值得分享。我这样做是为了找到“公共静态无效”方法,即播放控制器操作,我使用 grep 从 Windows/Cygwin 命令行完成;请参见: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”开头的函数自动变成变量。不适用于“默认”访问级别,但我自己没有使用那么多。
(public|private|static|protected|abstract|native|synchronized) +([a-zA-Z0-9<>._?, ]+) +([a-zA-Z0-9_]+) *\\([a-zA-Z0-9<>\\[\\]._?, \n]*\\) *([a-zA-Z0-9_ ,\n]*) *\\{
上面的正则表达式将检测所有可能的 java 方法定义。在大量源代码文件上进行了测试。要同时包含构造函数,请使用以下正则表达式:
(public|private|static|protected|abstract|native|synchronized) +([a-zA-Z0-9<>._?, ]*) +([a-zA-Z0-9_]+) *\\([a-zA-Z0-9<>\\[\\]._?, \n]*\\) *([a-zA-Z0-9_ ,\n]*) *\\{
从 git 2.19.0 开始,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]*\\([^;]*)$"
(第一行似乎用于过滤掉类似于方法声明但并非如此的行。
这将选择方法的名称,而不是整行。
(?<=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+
这可以完全定义和分离一个 java 函数
(?<access>public|private|protected)?\s*(?<static>static|non-static)?\s*(?<final>final|non-final)?\s*(?<type>void|\w+)\s+(?<name>[a-zA-Z0-9_]+)\((?<parameter>.*?)\)\s*\{(?s)(?<body>.*?)\}
兼容:
- PCRE2 (PHP >= 7.3)
- JAVA8的
组:
- 访问方式:公共
- static:静态
- 决赛:非决赛
- 类型:void
- 名称:Main
- 参数: String[] 参数
- body: // 这是一个 Java 函数
这是一个正则表达式,不仅可以检测大多数类型的 Java 方法签名,还支持潜在的异常抛出(零个或多个异常类)、具有点的数据类型和泛型。
注意:请注意,在使用此正则表达式时,该方法必须包含访问修饰符(public、private 或protected):
\b(public|private|protected)\s*(<[^>]*>)?\s*(abstract|default|static|synchronized|final|native|transient)?\s*(abstract|default|static|synchronized|final|native|transient)?\s*(abstract|default|static|synchronized|final|native|transient)?\s+[^*](\w+(\.\w+)*)*(\s*<[^>]*>)?(\s*\[[^\]]*\])*(\s+\w+\s*\([^)]*\)(\s+throws\s+\w+(\s*,\s*\w+)*)?)+
评论