よくあるWikiStyle記法(いまだとMarkdownと呼ぶのが流行り?) でHTMLのtable要素をテキストで生成させる記法にこんなのがあったりする。
...
|a|b|c|
|foo|bar|baz|
...
↓
...
<table>
<tr><td>a</td><td>b</td><td>c</td></tr>
<tr><td>foo</td><td>bar</td><td>baz</td></tr>
</table>
...
この処理をsedでやらせてみる。各々の行は |
記号で挟まれた範囲を <td>...</td>
に置換すればよいので sed の s コマンドによる置換で一発でできそうだが、
行頭が | で始まる範囲の行全体を <table> と
</table> で括るのはどうしたらよいのだろう。
ホールドスペースを使って「行頭 |」を蓄えていき、 最後に全体を括るようにする。 たとえば、こんな感じのスクリプトで行ける。
#!/usr/bin/sed -f
/^|.*|/ {; # 行頭 | のあと1個以上の | がある行なら
s,|$,,; # まず行末の | を消しておく
s,|\([^|]*\),<td>\1</td>,g; # |... を <td>...</td> に置換する
s,^,<tr>,; s,$,</tr>,; # 行頭に <tr> を、行末に </tr> を付加
H; # 置き換え結果をホールドスペースに追加
s/.*//; # パターンスペースは出力されないよう消しておく
# ↓最終行なら残ったホールドスペース処理のため :cont へ
$ b cont
d; # 最終行以外なら次のサイクルへ
}
:cont
x; # 行頭| 以外の行: まずホールドスペースと交換
/./ {; # ホールドスペースに文字列があれば
s|^|<table>|; s|$|</table>|; # 先頭に <table> を、末尾に </table> を追加
p; # <table>...</table>全体を出力する
s/.*//; # 出力し終わったら消しておく
}
x
# ここで最後にパターンスペースにある内容が出力される