罫線をテキストに表示する
これ見て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を設定している。
数値の場合は右寄せ、その他は左寄せ。数値の正規表現による判断は適当。
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