LinuxでのSedの使い方

大量のコードを表示している2台のコンピュータモニターの写真

Sedは、ファイルを作成したり編集したりしないシンプルなUNIXプログラムです。入力を通過するデータのみを修正し、修正されたデータを出力として表示します。ここでは、UNIX哲学の簡単な概要を見てから、sedの基本を解説し、日常のタスクにこのプログラムをどのように使用するかの例を示します。

目次

  • Sedの基本
    1. テキストストリームの選択とトリミング
    1. Sedストリームからのテキストの削除
    1. Sedストリームに新しいテキストを追加
    1. Sedでのテキストの検索と置換
    1. テキストデータをホールドスペースにコピー
    1. Sedでのループを作成するためのラベルの使用
    1. Sedでの永続的な変更

Sedの基本

Sedは、テキストデータストリームを読み取り、修正することができるプログラムです。これは、通常のテキストエディタとは異なり、sedはコンピュータ内のファイルを直接変更しません。代わりに、受信データの「フィルター」として機能し、データを望むように変換することができます。

まず、sedを始めるには、内部に少なくとも5行のテキストを含むファイルを作成します。行の間に「改行」文字があることを確認してください:

printf "hello\nmaketecheasier\nworld\nthis\nis\nwonderful\n"> hello.txt

注意: このガイドではsedをデモンストレーションするためにマルチラインテキストファイルを使用していますが、プログラムのすべてのサブコマンドはUNIXパイプから来たテキストにも機能します。

Sedの一般的なコマンドは以下のようになります:

sed [option] '{script}' [text file]

Sedで最も基本的な機能の1つは、nサブコマンドです。これは、sedの入力からデータを読み取り、そのプログラムの「パターンスペース」に配置します。これは、sedがデータに操作を行う前に、任意の受信テキストを保持する特別なバッファです:

sed n hello.txt

Sedのもう1つの基本的な機能は、pサブコマンドです。nと同様に、sedの入力から入ってくるデータを読み取り、プログラムのパターンスペースに配置します。ただし、明示的にそれをターミナルの出力に印刷します。

pサブコマンドを使用すると、初心者には混乱を招くことがあります。テキスト入力で実行すると、sedが出力を2回印刷する結果になります。これは、デフォルトでsedはpが存在するかどうかに関わらず、パターンスペースを自動的に印刷するからです:

sed p hello.txt

-nフラグなしでpサブコマンドの出力を表示しているターミナル

この奇妙な動作を無効にするには、sedサブコマンドを実行する前に-nフラグを追加します:

sed -n p hello.txt

-nフラグを有効にしてpサブコマンドの出力を表示しているターミナル

基本が分かったところで、次のセクションではテキストデータを操作するためにsedをどのように使用できるかのさまざまな方法を見ていきます。

1. テキストストリームの選択とトリミング

印刷するだけでなく、sedを使ってデータストリームやファイルからテキストを選択してトリミングすることもできます。これを行う最も簡単な方法は、pサブコマンドに範囲値を追加することです。

次のコマンドは、sedの範囲構文を使用して「hello.txt」ファイルの3行目から5行目を印刷します:

sed -n '3,5p' hello.txt

特定の行範囲を印刷するsedの能力を示すターミナル

pサブコマンドを使用して、テキスト内の非隣接行を印刷することもできます。例えば、次は「hello.txt」ファイルの1行目と4行目を印刷します:

sed -n '1p; 4p' hello.txt

2. Sedストリームからのテキストの削除

Sedは、受信するテキストストリームからデータを削除することもできます。これは、大きなファイルから数行のテキストを削除したり、プログラムの出力を整理して必要な情報だけを表示したりする場合に役立ちます。

これを行うには、削除したい特定の行または範囲と一緒にdサブコマンドを使用します:

sed -n '2d; 5d; p' hello.txt

sedを使用して非隣接行を削除するプロセスを示すターミナル

テキスト行を印刷する場合と同様に、dサブコマンドはマルチライン範囲で機能します。例えば、次のコマンドは「hello.txt」ファイルの最初の4行を削除します:

sed -n '1,4d; p' hello.txt

特定の行範囲に一致することに加えて、正規表現を使用して削除したいテキストを見つけることもできます。これにより、sedは「world」という単語を含む行を探して削除します:

sed -n '/world/ d; p' hello.txt

正規表現を入力ファイルの範囲として扱うこともできます。これにより、プログラム内での選択をより柔軟に定義できます:

sed -n '/world/,/wonderful/ d; p' hello.txt

正規表現パターンに基づいてテキスト行を削除するsedの能力を示すターミナル

3. Sedストリームに新しいテキストを追加

テキストの削除に加えて、sedは既存のデータストリームに新しいテキストを追加することもできます。完全なテキストエディタのレベルではありませんが、この機能は一時的な編集や基本的なテキスト追加に役立ちます。

新しい行のテキストを追加するには、aコマンドを使い、追加したいテキストの後に続けます:

sed -n '$a hello' -e 'p' hello.txt

sedストリームの最後に1行のテキストを追加するプロセスを示すターミナル

注意: -eフラグは、引用された文字列がsed式であることをsedに伝えます。これにより、sedを複数回呼び出すことなく、複数の式を連結できます。

ファイル全体をsedテキストストリームに含めることもできます。これを行うには、追加したいファイルの名前の後にrコマンドを使用します:

sed -n '$r welcome.txt' -e 'p' hello.txt

sedストリームの最後にファイル全体を追加するプロセスを示すターミナル

4. Sedでのテキストの検索と置換

Sedの最も強力な機能の1つは、テキストストリーム内のテキストを検索して置換する能力です。テキストを追加したり削除したりするのとは異なり、これはUNIXパイプを通過する際にデータを動的に編集できるため、通常のテキストエディタに比べてはるかに柔軟です。

まず、sedからの変更なしにテキスト入力を印刷します:

sed -n 'p' hello.txt

sedを使って

pサブコマンドをsに置き換え、その後に三重スラッシュ(/)を追加します:

sed -n 's///' -e 'p' hello.txt

マッチさせたい文字列を最初と二番目のスラッシュの間に挿入します。例えば、私の入力文字列の中で「wo」で始まる単語を探すために以下の値を入力できます:

sed -n 's/wo*.//' -e 'p' hello.txt

テキストカーソルを二番目と三番目のスラッシュの間に置き、マッチを置き換えたいテキストを提供します。このセクションでは構造的な正規表現を使用しません:

sed -n 's/wo.*/website/' -e 'p' hello.txt

デフォルトでは、sedは特定の行の中でマッチした最初の文字列のみを置き換えます。テキストストリーム内の単語のすべてのインスタンスを置き換えたい場合には、この問題が生じる可能性があります。これを修正するには、式の3番目のスラッシュの後にgオプションを追加します:

sed -n 's/wo.*/website/g' -e 'p' hello.txt

sedの置換サブコマンドを示すターミナル

5. テキストデータをホールドスペースにコピー

Sedは、テキストデータを格納するために2つのバッファを使用します:パターンスペースとホールドスペース。前者は、sed式を通過する際のテキストの一時的な場所として機能します。一方、後者は任意のテキストデータを保存するためのクリップボードとして機能します。

このアプローチの利点の1つは、外部プログラムに依存せずに特定の出力を「保持」できることです。これは、sedを使って複雑なテキスト操作を処理しようと計画している場合に便利です。

ホールドスペースを使用するには、まず、内部に数行のテキストを含むファイルがあることを確認します:

sed -n 'p' hello.txt

pサブコマンドをhに置き換え、sedがファイル内で一致させる行番号または正規表現の値を提供します。これにより、sedはその特定の行のテキストを取り出し、ホールドスペースにコピーします:

sed -n '3h' hello.txt

注意: ホールドスペース内のデータは、異なるsedコマンドを跨いでは持続しません。

Hサブコマンドを使用して、ホールドスペース内に複数の行のテキストを保存することもできます。例えば、次のコマンドは、テキストファイルの3行目と4行目を保存し、ターミナルに再表示します:

sed -n '3,4H; $ {x; p}' hello.txt

sedのホールドスペースに複数行のテキストを保持するプロセスを示すターミナル

6. Sedでのループを作成するためのラベルの使用

Sedは包括的なプログラミング言語ではありませんが、プログラム内にループを作成することは可能です。これは、特定のテキスト入力を何度も処理する必要があるsed式に役立ちます。

Sedでループを作成するには、まず、sed式のためのラベルを作成する必要があります。そのためには、:サブコマンドの後に使用したいラベルを書きます。

sed -e ':x' hello.txt

Sed式の一致基準を提供します。私の場合、入力テキストの各行の最後に移動するようにしたいです:

sed -e ':x; $' hello.txt

マッチが見つかったときに実行したいsedサブコマンドをタイプし、それを中括弧で囲みます。次の例では、2つの隣接行を結合し、改行文字をスペースに置き換え、式の最初に戻ります:

sed -e ':x; /$/ {N; s/\n/ /g; bx}' hello.txt

sedラベルを使って改行文字を取り除くプロセスを示すターミナル

このアプローチは、ほとんどあらゆる種類の入力テキストに適用できます。例えば、次のコマンドはsedの拡張正規表現機能を使用して、入力テキストからHTMLタグを取り除きます:

sed -re ':x; s/<[^>]*>//g; {N; bx}' hello.html

ループを使用してファイル内のHTMLタグを削除するsedのプロセスを示すターミナル

7. Sedでの永続的な変更

他のUNIXツールと同様に、sedは出力リダイレクションとパイプも活用できます。これにより、sedを他のプログラムと組み合わせることができ、変更を永続的に残すチャンスも得られます。

次のコード行は、sedコマンドの出力から新しい「welcome.txt」ファイルを作成します:

sed -n '2p; 6p' hello.txt > hi.txt

出力リダイレクションを使用して、sedの出力をファイルに保存する能力を示すターミナル

出力リダイレクションの他に、現在のファイルを編集するために、-iフラグを使用することもできます。例えば、次のコマンドはテキストファイルから改行文字を削除し、その変更を保存します:

sed -i -e ':x; $; {N; s/\n/ /g; bx}' hello.txt

ターミナルにおいてsedの-iフラグを使って

もしこの会話がLinuxコマンドラインに興味を持たせたなら、過去の記事を読むことができます。そこでのいくつかの最も興味深いBashプロンプトについて話しています。