ソースツリーでコンテンツごとにファイルを再帰的に探したいです。 grepを使って以下を試しました。
$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)
これは私が望むように各行を返しますが、私は次のように変更しました。
$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)
しかし、ファイル名を印刷する代わりに
(standard input)
標準出力として印刷します。各ファイル名とパス(sed
使用)を取得するには、この問題をどのように解決する必要がありますか?
私がしたいこと:printf
次の行を含むすべてのファイルを見つけて、見つけた%s
ファイルbcm_errmsg(rv)
に次のsedコマンドを適用します。
sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'
答え1
私の考えでは、あなたが物事をあまりにも複雑に思うと思います。foo
現在のディレクトリとサブディレクトリのすべてのファイルで文字列を見つけるには、次の手順を実行します。
grep -r "foo" *
デフォルトでは、grepは見つかったファイル名の前に一致する行を出力します。
以下は、一致する行ではなくファイル名のみを出力します。
grep -rl "foo" *
答え2
@steeldriverの元のアイデアに応じて、次のようにすることができます。
egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'
答え3
grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
/%s/!b
/printf/!b
/bcm_errstr(rv)/!b
s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'
まず、再帰ディレクトリを実行します。同じ行にあるprintf、%s、およびbcm_errstr(rv)文字列を使用して現在のディレクトリからファイルをスキャンしますが、順序は可能です。grep
これを行うのに役立つオプションは次のとおりです。
-r
=>現在のディレクトリとその下のすべてのファイルを再帰的に起動します。-l
=>は、基準に一致するファイル名を一覧表示します(たとえば、同じ行にある3つの文字列すべて)。-Z
=>選択したファイル名は、通常の改行(\ n)ではなくスペースで区切られた(\ 0)形式なので、任意の種類のファイル名を処理できます。-P
=> Perl正規表現エンジンを有効にして、プレビューを使用して3つの文字列が同じ行にあることを確認できます。
パイプのもう一方の端には、xargs
\ 0で区切られたファイル名がリッスンしています。その後、できるだけ多くのファイル名をsedコマンドラインに渡します。前の質問でsubsを実行するsedコマンドをすでに知っています。同じ行に3つの文字列を含む行にのみ適用されます。