awk 演習:タグ値ペアを扱う2009年03月13日 09時25分23秒

プロセス間通信にタグと値を対にした書式を使うと、送る項目に柔軟性が持てる。構造体などを使った通信だと、何を送るべきなのか事前に正しく把握する必要がある。文字列の羅列として処理出来る形式を選ぶことで変更にも対処しやすくなる。また、メッセージをしかし、処理速度に難点があるなど、万能でも無い。

文字をエスケープするのを避ける為に、書式には柔軟性を持たせる。区切り文字は文字列の最初の文字を用いる。タグには空白以外の任意の文字を使える。タグの後に空白一つが入り、それ移行は区切り文字までが、全て値とする。

例をあげると、|product book|price 1000|pages 135|paper_size B5| 等として、本の属性を表せる。 この形だと、実用上ではエスケープ文字などを作らないでの運用が可能になり、二文字を用いて一文字を洗わす処理が回避できる。例えば、\n を用いて ASCII の改行を示すのは、よくプログラム言語で使われる。

これらの値を一括変換したり、一部だけ抽出するのに awk が使える。


% cat tag-value.awk
{ # break each component of tag-value into a hash table
  FS = substr($0, 1, 1)
  for(i in pairs) delete pairs[i]
  for(i = 1; i <= NF; i++)
  {
    tvsplit($i)
    pairs[key] = value
  }
}
{
  print tvmsg(pairs)
}
function tvsplit(word){
  key = substr(word, 1, index(word, " ") - 1)
  value = substr(word, 1 + index(word, " "))
}
function tvmsg(attr){
  msg = sprintf("%s", FS)
  for(i in attr)
    if(attr[i] != "")
      msg = msg sprintf("%s %s%s", i, attr[i], FS)
  return msg;
}

この例では、一度分解した後に再構築しているだけなので、希望の処理を適時いれる。awk ではライブラリを作りづらいのが難点だ。gawk 等、複数のプログラムを指定できるなど拡張されている場合もあるが、古い処理系だとそれも出来ない。awk は書き捨てと潔く諦め、必要最低限に留めている。

例えば、全ての値段を 10% 上げる場合は、pairs["price"] = pairs["price"] * 1.1 等として使う。