ファイル内の文字列を再帰的に置換する

ファイル内の文字列を再帰的に置換する

page_path\example_filename.txt文字列内のバックスラッシュをスラッシュに置き換えたいです。また、これを大規模なファイル システムで実行し、すべてのディレクトリを再帰的に検索できるようにしたいと考えています。

ウェブ上で、、、を使用するように言っている人を見つけましたgrepxargssedうまくいきませんでした。区切り文字やエスケープ文字のさまざまなバリエーションを試しましたが、うまくいきませんでした。

実行しようとしたコマンドは次のとおりです。
grep -lr -e 'page_path\\' * | xargs sed -i 's/page_path\/page_path//g'

前もって感謝します。

答え1

を使用するとgrep | xargs、ファイル名内の空白、引用符、バックスラッシュ (実装によってはその他もろもろxargs) で問題が発生します。

grepおよびの GNU 実装では、区切り文字としてゼロバイトを使用する をxargs使用することでこれらの問題を回避できます。grep -lZr ... | xargs -r0 sed ...

さて、sed コマンドについてですが、コツは、s/a/b/区切り文字として他の文字の代わりに使用できることです。例s#a#b#:

sed -i 's#page_path\\#page_path/#g'

答え2

また、そのためには find を使うこともできます:

find /your/path -type f -exec grep -l 'page_path\\' {} \; -exec sed -i 's#page_path\\#page_path/#g' {} \;

2 番目の exec は最初の exec が成功した場合にのみ実行され、ファイル名に印刷できない文字やエスケープが必要な文字に関する問題は発生しません。

答え3

なぜCPUサイクルを無駄にして、それらのコマンドをすべて呼び出すのでしょうか?バッシュはるかに少ない入力で実行できる機能が組み込まれていますか?

str='page_path\example_filename.txt'
echo "${str//\\/\/}"

出力

page_path/example_filename.txt

答え4

ripgrepここでも役立ちます。foo を一致させたいものに置き換え、rg呼び出しとsed式の両方を変更します。

rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'

ファイル名に空白文字が含まれている可能性がある場合は、ripgrepにNULLバイトで区切るように指示します。

rg foo --files-with-matches -0 | xargs -0 sed -i 's/foo/bar/g'

ソース:https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#検索と置換

関連情報