よくある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 # ここで最後にパターンスペースにある内容が出力される