ここに私のコマンドがあります(意図的な中断):
grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i '' '/FOO/{s/FOO/BAR/g; w /dev/stdout
}'
高レベル:grep
ディレクトリーのFOOの場合はblah
。 (-l
のため)ファイル名のみをsed
にパイプします。 sed
はインライン置換(-i ''
)を実行し、変更された用語のみを/dev/stdout
に出力します。
-l
とパイプを省略した場合、grep
からこれを取得します。
/Users/gjtorikian/blah/baz.cs:1:FOO
/Users/gjtorikian/blah/bar.js:1:FOO
私が欲しいのは、インライン置換を実行するsed
で、置換されたファイルと用語を表示します。例えば:
/Users/gjtorikian/blah/baz.cs:1:BAR
/Users/gjtorikian/blah/bar.js:1:BAR
そのようなことは可能ですか?それが重要な場合は、grep
/sed
のみを使用することをお勧めします。 grep
の後に2回目のsed
を実行する必要がありますか?
1つの可能性は、grep
の出力を別のsed
フィルターに渡すことです。
grep -l FOO "/Users/gjtorikian/blah/"* |
{ tee /dev/fd/3 |
xargs sed -i -e '/FOO/{' -e 's/FOO/BAR/g' -e 'w /dev/stdout'
} 3>&1 | sed 's/:FOO$/:BAR/'
sed
に行番号を出力させることができます(=
コマンド)一致が見つかった場合、さらに後処理を行います。
おそらくawkを使用するほうが明確でしょう。
for x in "/Users/gjtorikian/blah/"*; do
awk '
sub(/FOO/, "BAR") {found=1; print FILENAME ":" NR ":" "BAR" >"/dev/stderr"}
1 {print}
END {exit(!found)}
' "$x" >"$x.tmp" && mv "$x.tmp" "$x"
done
私はネイティブスピーカーではないので、おそらく理解できませんでした。
ディレクトリを「grep」するには、「-r」が必要です。 '-l'を使用すると、ファイル名だけが出力され、最初に出現した後にgreppingが停止します。
# pattern=/home ; grep -l "$pattern" /etc/[a-z]* 2>/dev/null | while read line ; do echo "$line:$pattern" ; done
/etc/adduser.conf:/home
/etc/fstab:/home
/etc/fstab~:/home
/etc/libuser.conf:/home
/etc/mpd.conf:/home
/etc/mpd.conf~:/home
/etc/mtab:/home
/etc/netscsid.conf:/home
/etc/passwd:/home
/etc/passwd-:/home
/etc/sudoers:/home
/etc/sudoers.tmp~:/home
現在のディレクトリでFOOをBARに再帰的に置換します(静止モード)
grep -rl 'FOO' | xargs sed -i 's/FOO/BAR/'