本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、テキストファイルをフィルター処理で編集する「sed」コマンドです。
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。テキストファイルをフィルター処理で編集する「sed」コマンドです。
連載第53回、第54回、第55回、第56回、第57回、第213回に続き、sedの応用を説明します。
「sed」は「Stream EDitor」の略です。「sed スクリプトコマンド ファイル名」で、指定したファイルをスクリプトコマンドに従って行単位に処理し、標準出力へ出力します。ファイル名を省略した場合は、標準入力からのデータを処理します。
sedコマンドを利用する場合、パイプとリダイレクトを活用することが一般的です。
sed [オプション]
sed [オプション] スクリプトコマンド 入力ファイル
※[ ]は省略可能な引数を示しています
短いオプション | 長いオプション | 意味 |
---|---|---|
-r | --regexp-extended | スクリプトで拡張正規表現を使用する |
-e スクリプト | --expression=スクリプト | スクリプト(コマンド)を追加する |
-f スクリプトファイル | --file=スクリプトファイル | 実行するコマンドとしてスクリプトファイルの内容を追加する |
-i | --in-place | ファイルを直接編集する |
-i拡張子 | --in-place=拡張子 | ファイルを直接編集し、指定した拡張子でバックアップする(「-i」と「拡張子」の間には空白を入れない) |
--follow-symlinks | -iで処理する際にシンボリックリンクをたどる | |
-n | --quiet,--silent | 出力コマンド以外の出力を行わない(デフォルトでは処理しなかった行はそのまま出力される) |
-l 文字数 | --line-length=文字数 | lコマンドの出力行を折り返す長さを指定する(「-l」と「文字数」の間には空白を入れる) |
-s | --separate | 複数の入力ファイルを一続きのストリームとして扱わずに個別のファイルとして扱う |
-u | --unbuffered | 入力ファイルからデータをごく少量ずつ取り込み、頻繁に出力バッファを掃き出す |
-z | --null-data | NUL文字で行を分割する(通常は改行で分割) |
--posix | 全てのGNU拡張を無効にする | |
sedでは、「アドレス」と「コマンド」の組み合わせで処理を指定します。
アドレスには行番号や正規表現による指定が可能で、省略した場合は全ての行が処理の対象となります。
コマンド | 意味 |
---|---|
= | 現在の行番号を出力する |
a テキスト | テキストの追加。指定した位置の後ろに[テキスト]を挿入する(挿入するテキストに改行を含める場合は、改行の前にバックスラッシュを置く) |
i テキスト | テキストの挿入。指定した位置の後ろに[テキスト]を挿入する(挿入するテキストに改行を含める場合は、改行の前にバックスラッシュを置く) |
c テキスト | 選択した行を[テキスト]で置換する(挿入するテキストに改行を含める場合は、改行の前にバックスラッシュを置く) |
q | これ以上入力を処理せずに終了する(未出力分があれば、出力してから終了する) |
Q | これ以上入力も出力もせずに終了する |
d | 指定した行を削除する |
p | 処理した内容を出力する(「-n」オプション指定時は「p」コマンドがないと何も出力されなくなる) |
s/置換前/置換後/ | [置換前]で指定した文字列にマッチした部分を[置換後]に置き換える。複数マッチした場合は先頭のみ置換、全てを置換したい場合は、「s/置換前/置換後/g」のように「g」オプションを指定する |
y/元の文字列/対象文字列/ | [元の文字列]にあるものを、対象文字列の同じ位置にある文字に置換する(「tr」コマンドのように使用できる) |
# | コメント(スクリプト中、「#」以降がコメントとなる) |
sedコマンドは、「テキストを1行読み込み、sコマンドなどで編集操作を行い、出力する」という処理を行ごとに繰り返すことで、ファイルを編集します。一連の操作を行うsedコマンド内部の場所を「パターンスペース」と呼びます。
sedは、この「パターンスペース」とは別に、処理中のデータを一時的に保存しておく場所を備えています。これを「ホールドスペース」と呼びます。
パターンスペースとホールドスペースは独立していますが、sedのコマンドによって内容をやりとりできます。
例えば「h」コマンドで、現在のパターンスペースの内容を、ホールドスペースにコピーします。ただし、ホールドスペースにデータがあった場合は上書きします。上書きではなく、追加したい場合は「H」コマンドを使用します。
以下にホールドスペースとパターンスペースについて利用できるsedのコマンドを示しました。コマンドの処理は全て行単位です。
コマンド | 意味 |
---|---|
h | 現在のパターンスペースの内容を、ホールドスペースに上書きコピーする |
H | 現在のパターンスペースの内容を、ホールドスペースに追加する |
g | ホールドスペースに保存した内容を、パターンスペースに上書きコピーする |
G | ホールドスペースに保存した内容を、パターンスペースに追加する |
x | パターンスペースの内容とホールドスペースの内容を交換する |
前回に続き、ホールドスペースを使った処理を試してみましょう。処理内容は、読み込んだテキストを1行ずつ逆順に出力するというものです。「tac」コマンド(第111回)と同等の処理です。
以下のスクリプトにあるGは「ホールドスペースの内容をパターンスペースに追加」という処理です。上書きではありません。1行目の段階ではホールドスペースは空なので、「1!」(1行目以外)と指定しています。
hは「パターンスペースをホールドスペースに上書きコピー」するコマンドです。
pはパターンスペースの内容を「出力」するコマンドで、最終行($)のみ実行しています。
1!G #(1行目以外)ホールドスペースの内容をパターンスペースに追加する h #(全ての行)パターンスペースの内容をホールドスペースに上書きする $p #(最後の行)パターンスペースの内容を出力する
ファイルを1行ずつ読み込んだときに、パターンスペースとホールドスペースの内容がどのように変化するのかを、図1に示しました。それぞれの枠の中にある左側の円筒がパターンスペース、右側の円筒がホールドスペースの内容です。
1行目を読み込んだとき(上段)には、スクリプトの2行目にあるhコマンドだけが働きます。2行目を読み込んだ瞬間(中段)には、パターンスペースには2行目が、ホールドスペースには1行目が入っています。スクリプトの1行目のGコマンドが働くと、ホールドスペースに入っていた1行目の内容がパターンスペースの末尾に追加されます。スクリプト2行目のhコマンドが働くと、パターンスペースの内容がそのままホールドスペースに上書きされます。
次々とファイルの行を読み込んでいくと、パターンスペースに元とは逆順に行が入っていきます。最後の行を読み込むと、スクリプト3行目のpコマンドが働いて、パターンスペースの内容を出力します。
画面1では、逆順になっていることが分かりやすいように「nl」コマンド(第98回)を使って、/etc/shellsの内容を行番号付きで出力し、sedコマンドで逆順にしています。
sed -ne '1!G;h;$p' /etc/shells
(/etc/shellsの内容を逆順で出力する)
cat /etc/shells | sed -ne '1!G;h;$p'
(/etc/shellsの内容を逆順で出力する)
画面1の処理を実行中に、他のコマンドを実行できます。例えば文字列の置換です。
置換コマンドは、パターンスペースに対して行います。画面2では、sコマンドで、「bin」ディレクトリという文字を大文字に置き換えています。ここでは置換対象の文字列に「/」記号があるため、sコマンドの区切り文字を、「s%」と指定して「%」に変えています。
なお、「%」を使わず、sコマンドの区切り文字を「/」記号のままで処理したい場合は、「\」を使ってエスケープし、「s/\/bin\//\/BIN\//」と指定します。
sed -ne 's%/bin/%/BIN/%;1!G;h;$p'
s%/bin/%/BIN/% #「/bin/」を「/BIN/」に置き換え 1!G h $p
西村 めぐみ(にしむら めぐみ)
PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。
Copyright © ITmedia, Inc. All Rights Reserved.