grepした結果をsed(正規表現置換)したかったときにMacだとハマった話

だいたい基本的にLinux前提で書かれている

ググってよくみつかるのは以下のワンライナー

grep -r hoge * | xargs sed -i "s/hoge/hufa/g"

ハマってる話をあまり聞かない限りは、たぶんこれで基本的にできるんだろう。

Macだとsedがハマる

そもそもMacのsedはBSD経由のsedらしくて、GNU版のsedとは違うらしい。だから -i オプションがつかえなかった。ということでbrewgnu-sedいれた。port版もちゃんとあるらしい

brew install gnu-sed

コマンドは gesd になる。あとはgnu-sedなのでいつもどおりなsedが使える。と思う

あるプロジェクト以下の文字列を一括変換したかった

grep -rl hoge ./ | xargs gsed -e -i "s/hoge/hufa/g"

できたし!!!!
@xxxxxxx ++
@yyyyyyy ++
@zzzzzzz ++
@hhhhhhhh ++

補足とか

あんまりちゃんと理解してないけど各種オプションについて。
grepはファイルから文字列を正規表現で取り出すコマンド。いつものアレですね。 -r で再帰的に読むのでディレクトリ以下を操作できる。-l はマッチしたファイルのみ表示
xargs はパイプでリダイレクトしたときに標準出力をひとつにまとめるやつ、でいいのかな?ひとつひとつ読み込むより一気にまとめて読み込むのでパフォーマンスがいい、らしい。
gsedはGNU版のsed。 -i で文字列の置換。 -e で変換内容の表示。標準出力に出力してくれる。あとは正規表現で置換。
まあ、素直にLinuxGNU版をつかうか、Macは上記の魔法を使うって覚えちゃうし!!!!情弱乙!!!!

もういっこ補足
grep -rl hoge ./

これだと全部のファイルが対象になるのはいいけど、gitやmercurialを使っている場合はそっちの履歴までさかのぼってしまうかもしれない。なので、厳密には

find . -name "*.py" | grep hoge * | xargs gsed -e -i "s/hoge/huga/g"

こんな感じでfindで拡張子を指定したほうがいいかもしれない。未検証だけど。