【Linux】MacOSのsedコマンドでエラーが発生した時の対処法
MacOSでsedコマンドにiオプションをつけて実行した際にsed: 1: "test.txt": undefined label 'est.txt'と発生してしまい、思った通りの挙動にならなかったため、対処法をまとめました。
はじめに
Bashで開発環境の構築ファイルを作成していたら、sedにiオプションを付けて使用している箇所でエラーが発生しました。
開発環境
macOS: 12.0.1
余談
このエラーはLinux(GNU系)のsedか、macOS(BSD系)のsedかが鍵となっています。
お使いのsedがどちらなのか分からない場合には、以下のコマンドを試してみてください。
sed --version
Linux(GNU系)の場合は、以下のようにエラーが出ずにコピーライトなどの情報が表示されます。
sed (GNU sed) ....
macOS(BSD系)の場合は、--versionというオプションはないため以下のようにillgal optionと表示され、usageが表示されます。
sed: illegal option .....
解決方法
バックアップファイルを生成するようにする
macOS(BSD系)のsedはバックアップファイルを生成することで、下記コマンドでiオプションを使用できます。
sed -i '.bak' 's/[対象文字列]/[置換後文字列]/' [ファイル名]
または
sed -i.bak 's/[対象文字列]/[置換後文字列]/' [ファイル名]
バックアップファイルを生成せずにiオプションを使用する
「いちいちバックファイルを生成されると困る..!」といった場合には、拡張子の記述をなくすことでバックアップファイルの生成を行わずにiオプションを使用できます。
sed -i '' 's/[対象文字列]/[置換後文字列]/' [ファイル名]
なぜこのエラーが発生するのか
結論からまとめると、これはLinuxのsedとmacOSのsedは厳密には違うものだからです。
LinuxのsedはGNU系であり、macOSのsedはBSD系のコマンドとなっています。
特にiオプションを使用した際の挙動に違いがあります。
Linux(GNU)
GNU系の場合、以下のコマンドで文字列の置換 & ファイルデータの上書きができます。
sed -i 's/AAAA/ZZZZ/g' test.txt
macOS(BSD)
BSD系で上記と同じコマンドを実行すると、以下のようにエラーが出ます。
sed: 1: "test.txt": undefined label 'est.txt'
次にeオプションをつけて実行してみます。
sed -ie 's/AAAA/ZZZZ/g' test.txt
すると、エラーも表示されずにファイル内容が上書きされます。
しかし、よく見ると、test.txteという新しいファイルが生成されており、オプションとしてつけたはずのeが拡張子として判別されてしまいます。
GNU sedのインストール
Homebrewにある、gnu-sedをインストールするのも一つの手です。
brew install gnu-sed
インストール後、下記コマンドが使用できます。
gsed 's/AAAA/ZZZZ/g' test.txt
zshでaliasを設定する方法
GNU sedインストール後、gsedではなく、sedで入力したいという方はzshのエイリアスでsedをgsedと設定すると対応できますね。
# ~/.zshrc
alias sed='gsed'
私はGNU sedをインストールせずに、GNUのsedとBSDのsedを使い分けたかったので以下のように設定しています。
# ~/.zshrc
alias gsed='sed -i '' -e'
まとめ
macOSでsedを使用する際には、-iの後に''をつける必要があるので、それが面倒な方はgnu-sedのインストールを行うといいですね!
この記事がお役に立てば幸いです。
最後まで記事をご覧いただき、ありがとうございました。