UNIX の理念とは何か?
UNIX の哲学とは、プログラムは単一のタスクだけをうまくこなすべきだ という考え方です。他の作業に再利用できないような複雑なプログラムを作るのではなく、異なる機能に再利用できるような単純なプログラムを書くことを推奨しています。
この良い例が cat
というプログラムです。これは、入力を受け取り、それをテキストのストリームとして表示するだけの簡単なユーティリティです。
例えば、grep
のようなプログラムにcatストリームを送り込むことができます。これは単純なプログラムで、たった一つのことしかしない。入力から文字列を探し、その文字列が現れている行を表示します。
一方、同じcatストリームを less
のようなスクリーンページャーに送り込むこともできます。これにより、あたかも1つのテキストファイルであるかのように、ストリームをスクロールすることができるようになります。
Sed はどのように動くのか?
とはいえ、sed はテキストのストリームを読み、それを修正するプログラムです。しかし、sed はテキストストリームを変更するだけであり、コンピュータ内のファイルを 直接変更することはありません。これは、sed で行った変更がディスクに表示されないため、初心者にとっては混乱することでしょう。
それにもかかわらず、sed は依然として強力なユーティリティです。例えば、次の行を実行すると、 printf
コマンドの出力を読むことができます。
printf "hello ↵↵↵↵↵↵". | sed n
Sed の使い方の基本
これを知っていれば、sed を使って基本的な作業をするのは驚くほど簡単です。次のような例を考えてみましょう。
sed -n p hello.txt
この中で、n
コマンドを使って、ファイル「hello」の中身を表示しています。
1. テキストストリームの選択とトリミング
さらに、このテキストのストリームを変更するようにsedに指示することもできます。たとえば、 2q
コマンドを使用して、 “hello” ファイルの最初の 2 行だけを表示するように指示することができます。
sed 2q hello.txt
これは、テキストファイルの最初の数行だけを取得したい場合に、非常に便利です。しかし、 p
コマンドを使用して、ファイルの中のある範囲の行だけを表示するように sed に指示することもできます。
sed -n 3,4p hello.txt
上の例では、sed を使って “hello” ファイルの 3 行目と 4 行目を表示しました。また、同じ p
コマンドを使って、テキストファイルの隣り合っていない行を表示することもできます。次のような例を考えてみましょう。
sed -n 1~4p hello.txt
これで、「hello」ファイルの1行目と4行目だけを表示するようにsedに指示しています。これは、異なるストリームからの複数の行を一つのファイルにまとめたい場合に便利です。
たとえば、sed と >
演算子を使用して、変更されたストリームをファイルに書き出すことができます。
sed -n 1~4p hello.txt > welcome.txt
2. テキストの削除
sedのもう一つの素晴らしい機能は、ストリーム中のテキストを削除することです。印刷とは異なり、sed がストリームから削除したいテキストの行を選択することができます。
たとえば、私は d
コマンドを使用して hello ファイルの 2 行目と 5 行目を削除しました。
sed 2~5d hello.txt
p`コマンドの代わりにこれを使う利点の一つは、不要な行だけを削除できることです。これは、大きなファイルを整理したり、必要な情報のみを表示するために出力を切り詰めたりしたい場合に便利です。
3. 新しいテキストを追加する
新しいデータをテキストストリームに含めるために、sed をそれ自体で使用することもできます。たとえば、 a
コマンドを使用して、現在のストリームにテキスト行を追加することができます。
sed -n 2p hello.txt | sed a\ "this is a new line".
さらに、ファイル全体をテキストストリームに含めることも可能です。これを行うには、 r
コマンドを使用します。このコマンドを使用すると、1つのファイルを現在のストリームに読み込むことができます。これを行うには、次のコマンドを実行して、hello の 2 行目の後に welcome ファイルを含めます。
sed -n 2p hello.txt | sed rwelcome.txt
4. テキストの置換とストリームの操作
sedの輝かしい使い方の1つは、既存のストリームを変更することです。これは、テキスト入力ストリームを受け取り、そのストリームの内容を変更するために sed の組み込み関数を使用する場合です。
これは間違いなく sed の最も強力な機能です。この機能により、パイプを通過するデータを動的に編集することができるようになります。例えば、あるプログラムの出力をテキストファイルのように簡単に編集することができます。printf "hello 103". | sed s/world/website/
この例では、s
コマンドを使って、“world “という単語を “website “に置き換えています。しかし、これまでのコマンドとは異なり、このコマンドは正しく動作させるために特定の構文を使用します。
それを知っていると、s
コマンドの一般的な形式は次のようになります。
s/[正規表現]/(文字列)/{options} となります。
- 最初の列は、これが代用コマンドであることを示しています。ほとんどの場合、
s
コマンドはテキストストリームを変更するためだけに使用する必要があるでしょう。 - 2番目の列は、構造的な正規表現を使って置き換えたい単語を表します。これは、一般的な規則を使って単語や文法を記述する方法です。例えば、“prints”, “prince”, “primer” という単語は、
pri[n,m]...
という書き方で記述することができます。 - 3番目の列は、古い文字列にしたい単語を記述する。前の列とは異なり、この列は正規表現を使用しません。その代わりに、プレーンテキストを使用して新しい単語を記述します。
- 最後の列は、sed に置換のために必要な追加オプションを適用するように指示します。その中で、最もよく使われるフラグは
g
です。これは、このコマンドが正規表現のすべてのインスタンスを新しい文字列に置き換えることを意味します。
5. 5. ファイルでテキスト置換を使う
s` コマンドを使えば、どんな種類のテキストストリームでも操作することができます。これはデータをその場で修正できるだけでなく、Linuxのコマンドラインではほとんど全てのものに使えるので便利です。
例えば、コマンドの最後にファイル名を追加することで、テキストファイルに対して s
コマンドを使用することができます。
sed s/hello/welcome/ hello.txt
この例では、sed に “hello” ファイルを読み込んで、最初の “hello” という単語のインスタンスを “welcome” に置き換えるように指示しています。g` オプションを追加することで、ファイル中の “hello” という単語のすべてのインスタンスに対してこの処理を行うことができます。
sed s/hello/welcome/g hello.txt
Frequently Asked Questions (よくある質問)
sed を使ってファイルに変更を書き込むことは可能ですか?
はい! ファイル演算子を使う以外に、sed を使って変更したテキストストリームをファイルに直接書き込むことができます。これを行うには、sed に -i
フラグを付けるか、 w
コマンドを使用してストリームをファイルに書き込みます。
sed を使うたびに “unterminated” エラーになります。私のインストールは壊れているのでしょうか?
いいえ、そんなことはありません。これは、sed コマンドを適切に記述しなかったときに起こる問題です。これは、文字列を空白でマッチさせるか置換するような置換コマンドでよく起こります。
たとえば、次のようなコマンドを実行すると、“unterminated” エラーになります: sed s/hello/welcome back/g hello.txt
.
これで、上記のコマンドの正しいバージョンは次のようになります。sed s/hello/welcome\ back/g hello.txt
.
g” 以外に “s” コマンドで使用できるフラグはありますか?
はい、あります。g以外に、
p` フラグを使って、変更された行を表示させることができます。
sと一緒に使えるもうひとつのフラグは
eです。これは、sed が単語を置き換えるたびにシェルコマンドを実行するようにします。例えば、以下のコマンドを実行すると、ファイルの中に "hello" という単語を見つけるたびに
touch を実行することができます。
sed s/hello /touch} /e hello.txt`.
最後に、i
フラグを使って、sed がマッチを探すときに大文字と小文字を区別しないようにすることもできます。これは、同じ単語で異なる大文字小文字を区別してマッチさせたい場合に便利です。たとえば、次のコマンドは “hello” という単語を大文字小文字に関係なく “welcome” に置き換えます。sed s/HELLO/welcome/i hello.txt
.