grepはsedにパイプしてインラインを置き換えますが、sedはファイル名を印刷して行を変更したいと思います。可能ですか?

grepはsedにパイプしてインラインを置き換えますが、sedはファイル名を印刷して行を変更したいと思います。可能ですか?

私のコマンドは次のとおりです(意図的に中断されました)。

grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i '' '/FOO/{s/FOO/BAR/g; w /dev/stdout
}'

高レベルで:ディレクトリgrepのFOO。インライン置換()を実行し、ファイルblah名のみを-lパイプします。sedsed-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/それが重要な場合sedgrepしばらくしてくださいsed

ベストアンサー1

grep1つの可能性はの出力を渡すことです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

おすすめ記事