鳳鳴は祖父の俳号

日記 メモ そんなの

罫線をテキストに表示する

これ見てawkでできないかなとやってみた。
Excelの表を罫線ごとテキストに変換する - ITmedia エンタープライズ

サンプルデータとして以下を用意。
ptable.txt

H,He,Li,Be,B,C,N,O,F,Ne
1,2,3,4,5,6,7,8,9,10
1.01,4.00,6.94,9.01,10.8,12.0,14.0,16.0,19.0,20.2
,,,Beryllium

 カンマで区切られたテキストから項目を抜き出す。必要なのは最大の項目数と、最大の項目の長さ。

keisen0.awk

#! /usr/local/bin/gawk -f
#
# keisen 2012/01/11
#
BEGIN{
  FS=","
}
{
  if (MaxNF<NF) MaxNF=NF
  for (i=1;i<=NF;i++) {
    if (Wf[i]<length($i)) Wf[i]=length($i)
  }
}
END{
  for (i=1;i<=MaxNF;i++) {
    if (i<MaxNF) {
      printf("%s ",Wf[i])
    } else {
      printf("%s\n",Wf[i])
    }
  }
}

実行すると最大の項目の長さをスペース区切りで列挙したものを出力する。

4 4 4 9 4 4 4 4 4 4

 次に、この情報と元のデータを連結したものから表を作る。
keisen1.awk

#! /usr/local/bin/gawk -f
#
# Keisen 2012/01/11
#
BEGIN{
  if (getline<=0) errexit("")
  F=NF
  for(i=1;i<=NF;i++) {
    Wf[i]=$i
    Sf[i]=strm("-",$i)
  }

  Sline="+"
  for(i=1;i<=F;i++) {
    Sline = Sline Sf[i]
    if (i<F) Sline = Sline "+"
  }
  Sline=Sline "+"

  FS=","

}

{
  t="|"
  for(i=1;i<=F;i++) {
    n=$i; if (NF>F) n=" "
    if(match(n,"^[+-]*[.]*[0-9]+[.]*[0-9]*$")) {
      n=aright(n,Wf[i])
    } else {
      n=aleft(n,Wf[i])
    }
    t = t n "|"
  }
  print Sline
  print t
}

END{
  print Sline
}

func strm(s,n ,t,i) {
  t=s
  for(i=1;i<n;i++) t=t s
  return t
}

func aleft(s,w ) {
  while((length(s)<w)) s=s " "
  return s
}
func aright(s,w ) {
  while((length(s)<w)) s=" " s
  return s
}

func isnum(n ,i) {
}

func errexit(s ,m) {
  m = s " : " ERRNO
  print m > "/dev/stderr"
  exit -1
}

 最初の一行は空白での区切り、続いてカンマ区切りのデータを扱うようFSを設定している。
数値の場合は右寄せ、その他は左寄せ。数値の正規表現による判断は適当。

 で、bashによるシェルスクリプトにまとめた。

keisen.sh

#! /bin/sh
tempfile=/tmp/$$
while [ $# -ge 1 ]
do
  gawk -f keisen0.awk $1 > $tempfile
  gawk -f keisen1.awk $tempfile $1
  shift
rm $tempfile
done

実行結果は以下のとおり(MacOSX 16.8 SnowLeopard)

+----+----+----+---------+----+----+----+----+----+----+
|H   |He  |Li  |Be       |B   |C   |N   |O   |F   |Ne  |
+----+----+----+---------+----+----+----+----+----+----+
|   1|   2|   3|        4|   5|   6|   7|   8|   9|  10|
+----+----+----+---------+----+----+----+----+----+----+
|1.01|4.00|6.94|     9.01|10.8|12.0|14.0|16.0|19.0|20.2|
+----+----+----+---------+----+----+----+----+----+----+
|    |    |    |Beryllium|    |    |    |    |    |    |
+----+----+----+---------+----+----+----+----+----+----+

※等幅の表示について参考にさせていただきました:水中ノート

 漢字にも対応したかったが、全角/半角文字の判断が簡単に思いつかなかったので先送り。jgawkの頃はjlengthとlengthの違いで判断できたんだがなあ。正規表現でやるしかない?
 ちょっとシェルスクリプト書くのに時間かかった。慣れんなあ。自分で書く時はこの程度だけど、人に使ってもらう時はもうちょっとエラーチェックを厳密にやります。


以前はcsh使ってたけど今はbashの時代らしい。ようわからんで時間がかかった。
bash 例解: 第1回 Bourneシェルの生まれ変わり(bash)による初歩のプログラミング

以下は全角罫線のための資料
罫線素片 - Wikipedia