Регулярное выражение, которое будет соответствовать объявлению метода Java

StackOverflow https://stackoverflow.com/questions/68633

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

int foo()
{

}

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

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

Это было полезно?

Решение

Рассматривали ли вы возможность подбора реальных возможных ключевых слов?такие , как:

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

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

Другие советы

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

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

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

#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 допускает только last)
  • Максимум три уровня вложенных дженериков:(<...<...<...>...>...> ладно, <...<...<...<...>...>...>...> плохой).Синтаксис внутри generics может быть очень фальшивым, и все же это регулярное выражение кажется приемлемым.
  • Не требует пробелов между типами и их (необязательными) открывающими дженериками '<'
  • Распознает внутренние классы, но не запрещает использование двух точек рядом друг с другом, таких как 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

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

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

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

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

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

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

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

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

При этом будет выбрано имя метода, а не вся строка целиком.

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

Я создал регулярное выражение vim, чтобы сделать это для ctrlp/фанки основываясь на ответе Георгиоса Гусиоса.

    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 static void", т.е.Воспроизвести действия контроллера, и я сделал это из командной строки 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) {

Я нашел себа229ответ полезен, он отражает большинство сценариев, но не следующие,

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", в переменные.Не работает с уровнем доступа "по умолчанию", но я сам им не часто пользуюсь.

Начиная с git 2.19.0, встроенное регулярное выражение для Java now, похоже, работает хорошо, так что в поставке вашего собственного, возможно, нет необходимости.

"!^[ \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]*\\([^;]*)$"

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top