は、置換値の広い範囲を扱う時に、それは少しより堅牢にするために、スクリプトの簡単な書き換えで始まるのをみましょう、だけでなく、より速く:
#!/bin/bash
# escape regexp and replacement strings for sed
escapeRegex() { sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; }
escapeSubst() { sed 's/[&/\]/\\&/g' <<<"$1"; }
while read -r old new; do
find test -type f -exec sed "/$(escapeRegex "$old")/$(escapeSubst "$new")/g" -i '{}' \;
done <test.txt
そこで、我々test.txt
からのラインで空白で区切られたフィールド(old
、new
)のペアをループとは、インプレース標準sed
がfind
で見つかったすべてのファイルに置き換えて実行します。あなたのスクリプトにかなり似て
が、test.txt
から我々properly read lines(なし単語の分割、パス名/変数の展開、など)、我々は可能な限り(cat
などの外部ツールを呼び出す必要はありません、cut
、xargs
)バッシュの組み込みコマンドを使用します。 escape sed
metacharactersをold
/new
sed
のregexpと置き換え式として正しく使用するための値です。
今度はlogging from sedを追加してみましょう。
#!/bin/bash
# escape regexp and replacement strings for sed
escapeRegex() { sed 's/[^^]/[&]/g; s/\^/\\^/g' <<<"$1"; }
escapeSubst() { sed 's/[&/\]/\\&/g' <<<"$1"; }
while read -r old new; do
find test -type f -printf '\n[%p]\n' -exec sed "/$(escapeRegex "$old")/{
h
s//$(escapeSubst "$new")/g
H
x
s/\n/ -->/
w /dev/stdout
x
}" -i '{}' > >(tee -a change.log) \;
done <test.txt
上記sed
スクリプトがnew
に各old
を変更しますが、それはまた、我々は順番にchange.log
ファイルに追加/dev/stdout
(バッシュ固有)、へold --> new
行を書き込みます。 find
の-printf
アクションは、処理されるファイルごとにファイル名の「ヘッダー」行を出力します。ただ、完全性について
[file1]
hostname=abc.com --> hostname=xyz.com
[file2]
[file1]
db-host=abc.com --> db-host=xyz.com
[file2]
db-host=abc.com --> db-host=xyz.com
、迅速なウォークスルーsed
スクリプト:これにより
、あなたの「変更履歴」のようになります。我々は、old
値を含む行にのみ作用する。そのような行ごとに、スペース(h
)を格納するために格納し、new
に変更し、その新しい値を今度はold\nnew
を保持する保持スペース(改行で結合された、H
)に追加します。パターンスペース(x
)を保持するので、old --> new
に変換するs
コマンドを実行することができます。それをに書き込んだ後、new
をホールドからパターンスペースに戻して、処理されたファイルに書き込まれます(インプレース)。
素晴らしいですが、うまくいきます。ありがとう! – vivekyad4v