複数のファイルには非常に長く複雑な文字列があり、それを再帰的に削除/交換したいと思います。文字列には、多くのスラッシュ、バックスラッシュ、スペース、およびすべての種類の特殊記号が含まれています。どうすればいいですか?単純なfind + sedの組み合わせは機能しません。なぜなら、すべての特殊記号のためにほとんどエスケープできないからです。
ファイルに検索文字列を書き、それを検索および置換コマンドの入力として使用できますか?
答え1
文字列には、改行文字とヌルバイトを除く任意の文字を含めることができると仮定します。 sedパターンとして使用するためにこの文字列を引用することができます。これらの文字$*./[\^
の前にはバックスラッシュが必要です。代替テキストでは文字を引用する必要があります\&/
。
regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\\&:g')
replacement=$(printf %s "$new" | sed 's:[\&/]:\\&:g')
sed -e "s/$regexp/$replacement/g"
Perlがあれば、はるかに簡単です。
export old new
perl -pe 's/\Q$ENV{old}/$ENV{new}/'
現在のディレクトリとサブディレクトリのすべてのファイルに対して繰り返し動作します。
regexp=$(printf %s "$old" | sed 's:[$*./\[^]:\\&:g')
replacement=$(printf %s "$new" | sed 's:[\&/]:\\&:g')
export regexp replacement
find . -type f -exec sh -c 'for x; do sed -e "s/$regexp/$replacement/g" <"$x" >"$x.new" && mv "$x.new" "$x"; done' _ {} +
または
export old new
find . -type f -exec perl -i -pe 's/\Q$ENV{old}/$ENV{new}/' {} +
答え2
-f
はい、そのオプションを使用して[list]式を含むファイルを指定できる必要があります。
-f script-file, --file=script-file
add the contents of script-file to the commands to be executed
しかし、まだ特殊文字をエスケープする必要があります(私の知る限りgrepと同等のsedはありません)。システムにPerlがある場合は、Perlを使用し、引用符付き文字列修飾子を--fixed-strings
使用することをお勧めします。\Q...\E