前回、sedコマンドで置換を実施する際の関数「s」について解説した。実は、このsedコマンドでも、grepコマンド同様、正規表現を利用することができる。ただし、利用する際は実装系の違いに応じて注意が必要だ。今回は、そのあたりについて説明しよう。
置換関数「s」で使える正規表現
sedコマンドで利用できる正規表現は、基本的に「IEEE Std 1003.2 (POSIX.2)」で説明されている「基本正規表現」と「拡張正規表現」の2つだ。このあたりは、grep(1)とよく似ている。
ただし、sedコマンドはgrepコマンドとは実装系の面で事情が異なる。grepコマンドは、事実上「GNU grep」がデファクトスタンダードなので、実装系の違いを気にする必要がほとんどない。OSが変わっても利用できるgrepコマンドは、GNU grepであることが多いので、動作の違いに悩むことはないのだ。
一方、sedコマンドではそうは行かない。sedコマンドは、Macや*BSDで使われている「BSD sed」と、主にLinux系ディストリビューションで使われている「GNU sed」という実装系がある。提供されている機能はよく似ているものの、全く同じというわけではない。オプションも、利用できる正規表現も異なっている。
違いをざっくりまとめると、以下のようになっている。
- (a) BSD sed:基本正規表現
- (b) BSD sed -E:拡張正規表現
- (c) GNU sed:基本正規表現+GNU sedの拡張表現
- (d) GNU sed -r:拡張正規表現
移植しようとした際に問題になることが多いのは(c)のパターンだ。LinuxでGNU sedの拡張表記を使っていた場合、例えばそのままMacに持っていったとしても、(Macに実装されていることの多い)BSD sedでは利用できない。拡張正規表現でもないので、BSD sedで利用しようと思ったら記述されている正規表現を基本正規表現か拡張正規表現に書き換える必要がある。これはちょっと面倒だ。
また、「手元ではMacBookを使っているが、管理対象のサーバはLinux」というケースを考えてみよう。便利なスクリプトやコマンドは結局使い回すことになるので、LinuxでもMacでも実行できるsedの書き方が欲しくなってくる。だとすれば、何らかの方法で前述した問題が発生しないようにする必要がある。
そこで、ここではその問題を解消する3つの方法を紹介しよう。用途に応じて、扱いやすい方法をチョイスしていただきたい。筆者が提案する選択肢は、次のとおりだ。
- (A) 基本正規表現だけを使う
- (B) 拡張正規表現だけを使う
- (C) GNU sedだけを使う
汎用性が高いというか、移植性という面で無難な選択肢は(A)だ。基本正規表現だけで書いておけば、BSD sedでもGNU sedでも同じ挙動になることが多いので、移植の際も書き換える必要がない。この方法の問題点は、記述するパターンが拡張正規表現を使う場合よりも長くなってしまうかもしれない、ということくらいだ。
また、(B)の方法もお薦めだと思う。拡張正規表現を使う場合、BSD sedには「-E」を、GNU sedには「-r」を指定する必要がある。そのため、指定するオプションは書き換える必要があるが、便利な記述も使えるし、オプションを書き換えるだけならば、そう手間もかからないだろう。ちなみに、FreeBSDのsedにはGNU sed互換目的でオプション「-r」も用意されているので、-rで書いておくとLinux・FreeBSD間の移植は楽かもしれない。
3つ目の(C)という選択肢もアリだ。幸い、GNU sedは多くのOSに移植されているので、後からパッケージ管理システム経由でインストールして利用できることが多い。互換性など考えず、慣れ親しんだGNU sedのみに特化して利用するというのも、ある意味現実的な選択肢ではないだろうか。その場合、BSD sedがインストールされた環境では、GNU sedは「gsed」という名前になることが多いので、移植する際にはコマンドをsedからgsedに書き換えることになる。
どの方法を使ってもよいと思うが、もし後々コピペしたりしても問題がないようにしたいのであれば、最初にそのあたりをちょっと考えておく必要がある……ということを覚えておいていただきたい。