sed
を使用して文字列をインプレースで置換する場合、それが行う変更を(古いファイルと新しいファイルの差分に依存せずに)報告する方法はありますか?
たとえば、コマンドラインを変更するにはどうすればよいですか
find . -type f | xargs sed -i 's/abc/def/g'
オンザフライで行われた変更を確認できますか?
システムでサポートされている場合は、sed
のw
フラグを/dev/stderr
、/dev/tty
、/dev/fd/2
と一緒に使用できます。例えば。次のような入力file
foo first
second: missing
third: foo
none here
ランニング
sed -i '/foo/{
s//bar/g
w /dev/stdout
}' file
出力:
bar first
third: bar
file
の内容は次のように変更されました:
bar first
second: missing
third: bar
none here
したがって、あなたの場合、実行します:
find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
s//bar/g
w /dev/fd/2
}' {} \;
ファイルをその場で編集して出力します。
./ file1: bar stuff more bar ./ file2: ./ file3: 最初にバー 3番目:バー
original line >>> modified line
のようなものを印刷することもできます。例:
find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
h
s//bar/g
H
x
s/\n/ >>> /
w /dev/fd/2
x
}' {} \;
ファイルをその場で編集して出力します。
./ file1: foo stuff >>> bar stuff more foo >>> more bar ./ file2: ./ file3: foo first >>> bar first third:foo >>> third:bar
最初のパスでp
rintアクションを使用して、2つのパスでそれを行うことができます。
find . -type f | xargs sed --quiet 's/abc/def/gp'
どこ --quiet
を指定すると、sedはすべての行を表示せず、p
接尾辞は置換が一致した行のみを表示します。
これには、sedが表示しないという制限がありますwhichファイルは変更されますが、もちろん、さらに複雑に修正することができます。
それは可能ではないと思いますが、回避策として、代わりにPerlを使用することが考えられます。
find . -type f | xargs Perl -i -ne 's/abc/def/ && print STDERR'
altered行を標準エラーに出力します。例えば:
$ cat foo
fooabcbar
$ find . -type f | xargs Perl -i -ne 's/abc/def/ && print STDERR'
foodefbar
これを少し複雑にして、行番号、ファイル名、元の行、変更された行を出力することもできます。
$ find . -type f |
xargs Perl -i -ne '$was=$_; chomp($was);
s/abc/def/ && print STDERR "$ARGV($.): $was : $_"'
./foo(1): fooabcbar : foodefbar
現在のパターンをファイルに書き込むwフラグを使用できます。したがって、それを代替コマンドに追加することにより、連続した代替をファイルに報告し、ジョブの完了後にそれを印刷できます。また、置換後の文字列をgrepで色分けしたい。
sed -i -e "s/From/To/gw /tmp/sed.done" file_name
grep --color -e "To" /tmp/sed.done
wとそのファイル名の間にはスペースが1つだけ必要であることに注意してください。
Sedで作成されていない場合でもdiffで変更が表示される可能性があるため、これはdiffよりも優れています。
@terdonソリューションが好きです-これにはPerlが適しています。
ここに私の微調整したバージョンがあります:
コード
find /tmp/test -type f ! -name "*.bak" -exec grep -l '/opt/gridmon' {} \; | xargs -L1 Perl -ni'.bak' -e'$old=$_; s/\/opt\/gridmon/~/g && print STDERR "$ARGV($.):\n\tOLD:$old\tNEW:$_"'
出力例
/tmp/test/test4.cfg(13):
OLD: ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
NEW: ENVFILE ~/server/etc/gridmonserver.cfg
/tmp/test/test4.cfg(24):
OLD: ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
NEW: ENVFILE ~/server/etc/gridmonserver.cfg