sed
内部文字列置換を使用するとき(以前のファイルと新しいファイルの違いに依存せずに)変更を報告する方法はありますか?
たとえば、コマンドラインを変更する方法は次のとおりです。
find . -type f | xargs sed -i 's/abc/def/g'
では、変更はすぐに表示されますか?
答え1
システムでサポートされている場合は、sed
sw
フラグを一緒に使用できます/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
}' {} \;
ファイルをその場で編集し、以下を出力します。
./ファイル 1: バーのもの もっとバー ./ファイル2: ./ファイル 3: バー最初 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
}' {} \;
ファイルを所定の位置で編集して出力します。
./ファイル 1: fooのもの>>>バーのもの もっとfoo >>>もっとバー ./ファイル2: ./ファイル 3: foo まず >>> bar まず 3番目:foo >>> 3番目:bar
答え2
p
最初のステップでは、rint操作を使用して2つのステップでこれを実行できます。
find . -type f | xargs sed --quiet 's/abc/def/gp'
ここで、--quiet
sed はすべての行を表示せず、p
suffix は代替項目に一致する行のみを表示します。
sed が表示しない制限があります。どのファイルが変更されていますが、これをより複雑に変更すると確実に解決できます。
答え3
私はこれが可能だとは思いませんが、回避策は代わりにPerlを使用することです。
find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +
これは印刷されます変更標準エラーの行です。たとえば、
$ cat foo
fooabcbarabc
blah blah
$ find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +
foodefbarabc
$ cat foo
foodefbarabc
blah blah
より複雑にするために、行番号、ファイル名、元の行、変更された行を印刷することもできます。
$ find . -type f -exec perl -i -pe '
$was=$_; chomp($was);
s/abc/def/ && print STDERR "$ARGV($.): $was : $_"
close ARGV if eof' {} +
./foo(1): fooabcbarabc : foodefbarabc
各ファイル間でリセットがclose ARGV if eof
必要であることに注意してください$.
。
最初の行だけでなく、各行に表示されるすべての項目を置き換えるには、演算子g
にフラグを追加します。s///
答え4
私は@terdonの解決策が好きです。 Perlはこれに便利です。
調整されたバージョンは次のとおりです。
- 一致する文字列を持たないファイルは変更しようとしません。
- 変更されたファイルの以前のバージョンをバックアップします(.bakバージョンの作成)。
- 各ファイル/変更されていない行を一覧表示して読みやすくするために、その行の古いバージョンと新しいバージョンをインデントして下に配置します。
パスワード
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