質問
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 では最後のみ許可されます)
- ネストされたジェネリックは最大 3 レベル:(
<...<...<...>...>...>
わかった、<...<...<...<...>...>...>...>
悪い)。ジェネリックスの内部の構文は非常に偽物である可能性がありますが、それでもこの正規表現では問題ないように見えます。 - 型とその (オプションの) 開始ジェネリックス '<' の間にスペースは必要ありません
- 内部クラスを認識しますが、Class....InnerClass などの 2 つのドットが隣接することは妨げられません。
以下は生の 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*\\{?[^\\}]*\\}?"
これ 文法 と Georgios Gousios の回答は、正規表現を構築するのに役立ちました。
Java の正規表現エンジンはデフォルトで貪欲であると確信しています。つまり、 "\w+ +\w+ *\(.*\) *\{"
以来決して一致しません .*
括弧内は、開始括弧以降のすべてを読み込みます。交換することをお勧めします .*
[^)] を使用すると、閉じ括弧以外のすべての文字が選択されます。
注記: Mike Stone がコメントで私を訂正してくれました。ほとんどの人は実際にはコメントを開かないので (私はコメントに気づかないことが多いのはわかっていますが)、次のように書きました。
欲張りだからといって絶対に合わないわけではないのですが…。ただし、正規表現の残りの部分を満たすためにその後にさらに括弧がある場合は、括弧を食べます...たとえば、「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
オプションの 1 つ (x を考えてください) では、正規表現内で # コメントを使用できます。また、「 」の代わりに \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/ファンキー Georgios Gousios の回答に基づいています。
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+{'
私の出力の最後の 2 つのエントリは次のとおりです。
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 の組み込み正規表現 現在はうまく機能しているようですので、独自のものを用意する必要はないかもしれません。
"!^[ \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]*\\([^;]*)$"
(最初の行は、メソッド宣言に似ているがそうでない行をフィルタリングして除外するためのもののようです。)