Help us understand the problem. What is going on with this article?

sedでメールヘッダーの継続行を一行にまとめる

More than 3 years have passed since last update.

はじめに

1メール1ファイルの状態で、To:やCc:に特定のメールアドレスを含むものだけ抽出したいとか、ときかくFrom:行だけ全部取り出したいとかやろうとすると、ヘッダーの継続行の扱いがけっこう面倒くさいですね。

普通ならPerlやPythonで書けばよいのだろうけれど、sed で継続行を一行にまとめる処理を書いてみました。

sedは読み込んだ行はパターンスペースに配置して、このパターンスペースが操作の対象となりますが、もうひとつホールドスペースというのを持っていて、これをうまく使うことで複数行を処理できます。

サンプルコード

:top
/^$/q
/^[A-Za-z]/{
/^[Ff][Rr][Oo][Mm]:/b concat
/^[Tt][Oo]:/b concat
/^[Cc][Cc]:/b concat
b next
:concat
h; n
:loop
/^[[:space:]]/{
H; x; s/\n[[:space:]]*/ /; x; n;
/^[[:space:]]/b loop
}
x; p; x;
/^[A-Z]/b top
}
:next

解説

1 行目
:top

:で始まるのはラベル行です。

2 行目
/^$/q

ヘッダーにしか用はないので、ヘッダー部分が終了したら処理を打ち切ります。

3 行目 〜 17 行目

/^[A-Za-z]/{ ... }

ヘッダー行の先頭部分だったらこのブロックの中を実行します。

4 行目 〜 7 行目
/^[Ff][Rr][Oo][Mm]:/b concat
/^[Tt][Oo]:/b concat
/^[Cc][Cc]:/b concat
b next

From:, To:, Cc: のとき、:concat以降の結合処理にジャンプ(b concat)します。

そうでなければ、:nextのところにジャンプ(b next)します。

:next以降にコマンドはないので、sed は次の行の処理に移ることになります。

8 行目 〜 9 行目
:concat
h; n

現在の行をホールドスペースにコピーして(h)次の行を読み込みます(n)。

10 行目 〜 14 行目
:loop
/^[[:space:]]/{
H; x; s/\n[[:space:]]*/ /; x; n;
/^[[:space:]]/b loop
}

継続行を1行にまとめる処理です。

読み込んだ行が継続行であれば /^[[:space:]]/{ ... } のブロックの中が実行されます。

パターンスペースをホールドスペースに追加して(H)、改行と継続行先頭の空白を単一のスペースに置換します(s/\n[[:space:]]*/ /)。

xはパターンスペースとホールドスペースを入れ替えるコマンドです。sedの操作はパターンスペースに対してのみ実行可能なため、このように入れ替えを行います。

次の行を読み込んで(n)、さらに継続行であれば:loopのところにジャンプしてループを続けます(/^[[:space:]]/b loop)。

15 行目
x; p; x;

ホールドスペースには、1行にまとめられたヘッダー行が保存されているので、これを出力します。

16 行目
/^[A-Z]/b top

パターンスペースには次の行を読み込んであるため、ヘッダー行であれば先頭に戻って処理を続けます(/^[A-Z]/b top)。

注意

[[:space:]]

[:space:]はPOSIX正規表現で空白を示すメタ文字列です。文字セット([])の中でのみ効果を持つため、[[:space:]]のように書きます。

POSIX正規表現を理解しない、伝統的なsedでは [ スペース タブ ] といったように書きましょう。ただし、ターミナルに表示されているこの行を安易にコピー&ペーストすると、タブがスペースに展開されていたりしますので注意が必要です。

b コマンド

ラベルの後に ; で区切ってさらにコマンドを書くことができるのは GNU sed のみです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away