tjinjin's blog

インフラ要素多めの個人メモ

Mac環境でsedを使うときの注意

Macsedを使った際にはまったので書きます。ちょっとした処理をしたいときにワンライナーで済ませるときありますよね。そんなときに大活躍なsedですが、Macに標準で入っているsedRHEL系のLinuxに入っているsedとは違うようです。(その他ディストリビューションについては未確認)

Macの標準はBSD系のsedです。Centosなどに入っているsedMacではgsed)はGNUsedです。 同じsedですが大きな違いがあります。

-iオプションの使い方が違う

ファイルを置換してそのまま保存するときに-iオプションを使いますが、BSDsedではエラーになってしまいます。

$ 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.

ちなみにgnusedはこんな感じです。

-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"