Macでsedを使った際にはまったので書きます。ちょっとした処理をしたいときにワンライナーで済ませるときありますよね。そんなときに大活躍なsedですが、Macに標準で入っているsedはRHEL系のLinuxに入っているsedとは違うようです。(その他ディストリビューションについては未確認)
Macの標準はBSD系のsedです。Centosなどに入っているsed(Macではgsed)はGNUのsedです。 同じsedですが大きな違いがあります。
-iオプションの使い方が違う
ファイルを置換してそのまま保存するときに-iオプションを使いますが、BSDのsedではエラーになってしまいます。
$ sed -i 's/aaa/bbb/' Gemfile sed: 1: "Gemfile": extra characters at the end of G command $ sed -i -e 's/aaa/bbb/' Gemfile
-iだけだとエラーになってしまいました。次に-eをつけることでうまくいっているように見えますが、ls コマンドで確認すると
$ ls -l total 56 -rw-r--r-- 1 jin staff 88 2 23 21:28 Gemfile -rw-r--r-- 1 jin staff 88 2 16 23:38 Gemfile-e
-eがついたバックアップファイルができてる!!ということになります。
manコマンド で調べたらこのような説明文が載ってました。
-i extension Edit files in-place, saving backups with the specified extension. If a zero-length extension is given, no backup will be saved. It is not recommended to give a zero-length extension when in-place editing files, as you risk corruption or partial content in situations where disk space is exhausted, etc.
-i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if SUFFIX supplied)
diskスペースが枯渇してファイルが中途半端な状況でできてしまうリスクがあると書いてますね。誰かがやったんでしょうかね。 ちなみにBSD系のsedでもこうすることでバックアップファイルなしで置換ができるようです。
sed -i '' 's/aaa/bbb/' Gemfile
毎回空文字指定しても良いのですが、私は面倒なのでgnu sedを導入しaliasでこっちを使うようにさせています。brewコマンドでinstallして~/.zshrcでaliasの設定をさせるだけなので、それほど負荷でもないので困っている方は試してみてはいかがでしょうか。
brew install gnu-sed
alias sed="gsed"