Regex, который будет соответствовать декларации Java-метода

Мне нужно Regex, которое будет соответствовать объявлению java-метода. Я придумал тот, который будет соответствовать объявлению метода, но требует, чтобы открывающая скобка метода находилась в той же строке, что и декларация. Если у вас есть предложения по улучшению моего регулярного выражения или просто лучше, пожалуйста, отправьте ответ.

Вот мое регулярное выражение: "\w+ +\w+ *\(.*\) *\{"

Для тех, кто не знает, как выглядит метод java, я предоставлю базовый вариант:

int foo()
{

}

Есть несколько необязательных частей для java-методов, которые могут быть добавлены также, но это единственные части, которые гарантированно имеют метод.

Обновление: Мое текущее Regex "\w+ +\w+ *\([^\)]*\) *\{", чтобы предотвратить ситуацию, описанную Майком и адком.

Ответы

Ответ 1

Считаете ли вы подходящими ключевые слова? например:

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

Скорее всего, это будет правильно соответствовать, хотя это может также затруднить чтение регулярного выражения...

Ответ 2

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

Я думаю, что указанное выше regexp может соответствовать почти всем возможным сочетаниям объявлений Java-методов, даже те, которые включают в себя generics и массивы, являются аргументами возврата, которые регулярное выражение, предоставленное оригинальным автором, не совпало.

Ответ 3

Я также нуждался в таком регулярном выражении и придумал это решение:

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

Этот грамматический и ответ георгиоса Гусиоса были полезны для построения регулярного выражения.

ОБНОВЛЕНИЕ: Считал, что обратная связь tharindu_DG, сделал группы не захватывать, улучшенное форматирование.

Ответ 4

Посмотрев другие ответы, вот что я придумал:

#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 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 допускает только последний)
  • Три уровня вложенных дженериков не более: (<...<...<...>...>...> okay, <...<...<...<...>...>...>...> 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

Ответ 5

Я уверен, что Java regex engine по-прежнему жадна, что означает, что "\w+ +\w+ *\(.*\) *\{" никогда не будет соответствовать, так как .* в скобках будет есть все после вскрытия. Я рекомендую заменить .* на [^)], таким образом вы выберете все символы без закрытия.

ПРИМЕЧАНИЕ: Майк Стоун исправил меня в комментариях, и поскольку большинство людей действительно не открывают комментарии (я знаю, что часто их не замечаю):

Жадный не означает, что он никогда не будет соответствовать... но он будет есть parens, если есть больше паренек после удовлетворения остальной части регулярного выражения... так, например, "public void foo (int arg) {if ( test) {System.exit(0);}}" не будет правильно соответствовать...

Ответ 6

Я придумал это:

\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

Ответ 7

Совет:

Если вы собираетесь писать регулярное выражение в Perl, используйте опции "xms", чтобы вы могли оставлять пробелы и документировать регулярное выражение. Например, вы можете написать регулярное выражение, например:

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

Один из вариантов (подумайте x) позволяет # комментариям внутри регулярного выражения. Также используйте \s вместо ".\s обозначает любой" пустой" символ. Таким образом, табуляции также будут совпадать - это то, что вы хотите. В Perl вам не нужно использовать //, вы можете использовать {} или < > или | |.

Не уверен, что другие языки обладают этой способностью. Если они это сделают, используйте их.

Ответ 8

(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]*) *\\{

Ответ 9

Это выберет имя метода, а не всю строку.

(?<=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+

Ответ 10

Я построил regex 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|\{)+$

Ответ 11

Это более конкретный вариант использования, но он намного проще, чем я полагаю, его ценность. Я сделал это для поиска методов "public static void", т.е. Действия с контроллером Play, и я сделал это из командной строки Windows/Cygwin, используя grep; см. fooobar.com/questions/39430/...

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) {

Ответ 12

Я нашел ответ 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*

Надеюсь, что это поможет.

Ответ 13

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

Кроме того, здесь можно заменить последовательность, которую вы можете использовать в IntelliJ

$1 $2 $3(

Я использую его следующим образом:

$1 $2 aaa$3(

при преобразовании файлов Java в Kotlin для предотвращения функций, начинающихся с "get", автоматически превращаясь в переменные. Не работает с уровнем доступа "по умолчанию", но я не использую это сам.

Ответ 14

Начиная с 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]*\\([^;]*)$"

(Первая строка предназначена для фильтрации строк, которые похожи на объявления методов, но не являются.)