0

コードのブロック内の文字列を含むファイルの名前 (もちろん改行を含むことができます)、またはより具体的には、コンストラクター内の特定のメソッド呼び出し ( methodNameと呼びましょう) を見つける必要があります。現在のディレクトリとそのサブディレクトリにあるすべての Java コード ファイルを調べる必要があります。

考えられる一致は次のとおりです。

public myClass() {
  a(1);
  b();
  myMethod("abc");
  c(5);
}

これは私がこれまでに思いついた表現です:

find . -name *.java | xargs nawk '{print $0 "~("FILENAME")"}' | tr -d "\n" | grep -s -i -o 'public \w\+([^)]*).*methodName([^~]*~([^)]*)'

つまり...
- *.java ファイルは再帰的に検出されます
- 各行が出力され、その横にそれが属するファイル名が表示されます (検出された場所を追跡するため)
- grep を使用できるように \n が削除されますブロック内
- methodNameが検索されます。

問題は、.* を使用する必要があるたびに、式を次の式の否定に変更し、次に次の式に変更する必要があることです。例: if I need .*\~, I need to do ([^~]*~... それは良くありませんが、我慢できます。その文字列を否定することはより苦痛になるため、問題はmethodNameに付属しています。

何か案は?正規表現でそれを行うことはできますか?

4

2 に答える 2

1

あなたは貪欲に苦しんでいます。.*はデフォルトで貪欲になるため、可能な限り多く、すべてを消費します。すべてを処理した後でのみ、式の次の部分に一致させようとし、一致するmまでバックトラックします。.*パターンの残りの部分が見つかった場合、 ('public \w+([^)]*)') の前のパターンの最初の出現から.*( methodName([^~]*~([^)]*)) の後ろのパターンの最後の出現までのすべてに一致します。

解決策は、.*lazy:を作成し.*?て、完全な表現を与えることですpublic \w\+([^)]*).*?methodName([^~]*~([^)]*)

興味深いことに、否定された文字クラスを使用する回避策は、それを使用した場合に推奨される解決策ですが、同様のmethodNameことを行うと少し扱いに​​くくなる可能性があります。

参照:貪欲ではなく怠惰

于 2012-07-07T05:35:45.800 に答える
0

grep の代わりに、sed を使用してみてください。ここにあなたが始めるのを助けるかもしれない何かがあります:

find . -name *.java | xargs awk '{print $0 "~("FILENAME")"}' | \
sed -n '                                  # start sed with automatic printing suppressed
/public \w\+/,/^}/H                       # append all constructors to hold space
$!d                                       # stop here unless this is the last line
g                                         # copy hold space to pattern space
s/.*methodName([^~]*~(\([^)]*\)).*/\1/p   # if methodName is called, print the file name
'
于 2012-07-06T21:51:29.777 に答える