GAWK HTML 簡単 表作成
巷には表題のようなアプリや変換サイトがたくさんあるようです。AWK でも凝った作りでなければ、簡単なスクリプトで作成可能です。以下はサクラエディタマクロとして使っていますが、バッチファイル単体でも起動可能なものとなっています。
区切り文字は単体タブ(MSExcel等)、カンマ(csv)とスペース+タブ(HP上の表)を対象とし、それ以外は標準の FS
となります(スペース区切り等)。テーブルデータを先読みし FS
を事前検査しています。かなりいい加減ですが、FS
を自動判断します。
検査の都合上、フィールド数にバラツキのある表は正しく分けられません。
使用例 1:アプリから表をコピー
hard/soft | spec/version |
---|---|
CPU | core2duo 2.93GHz |
RAM | 4GB |
OS | Windows10 pro 32bit |
GAWK | 4.2.1 / 4.1.4 / 3.1.5jp for win32 |
SakuraEditor | 2.3.2.0 非インストーラパッケージ |
gcc | (MinGW.org GCC-8.2.0-1) 8.2.0 |
UTF-8 実行環境 | MSYS2/Bash |
プログラム用フォント | M+/Rounded M+ Regular |
JWCAD for Windows | 8.1 |
InternetBrowser | FireFox |
Microsoft Excel | 2013 |
※データにスペースが含まれるのでデフォルトFSのままだと滅茶滅茶な表になる。
使用例 2:直接csvを書いて変換する
AWK実践入門 | 技術評論社 | ISBN978-4-7741-7369-6 |
プログラミング言語AWK | 新紀元社 | ISBN4-7753-0249-3 |
AWKを256倍使うための本 | アスキー | ISBN4-7561-0162-3 |
使用例 3:サクラエディタを使用せずに利用する
表をコピーしてから tabletag.bat をダブルクリックすると、ヘッダかデータかを実行時に選ぶことはできませんが、クリップボード内の変換は行われます。ペーストすると、同様の結果が得られます。ですので、必ずしもサクラエディタが必要というわけではありません。
バッチファイルのショートカットを、デスクトップに配置すると便利に使えるかもしれません。
tabletag.vbs
1 : 'サクラマクロ tabletag.vbs
2 : 'クリップボードに格納されている表をHTML-Tableに変換する
3 : 'tabletag.bat, mshta_clip_out.cmd, tabletag.awk
4 : '上記3ファイルを同一フォルダ(tabletag)に格納
5 : 'batpathを設定し、当vbsファイルを\sakura\macros\に保存
6 : 'サクラエディタにマクロを登録(コンテキストメニューに追加)
7 :
8 : Option Explicit
9 : Const batpath = "y:\tabletag\tabletag.bat"
10 : Dim nselect, sprompt, nth, snz, scmd
11 :
12 : nselect = Editor.IsTextSelected()
13 : If nselect <> 0 Then
14 : sprompt = "選択された表をHTML-tableに変換し、" & vbCrLf & _
15 : vbCrLf & "クリップボードへ転送します" & vbCrLf & vbCrLf & _
16 : vbCrLf & "テーブルヘッダ 1 を入力"
17 : Else
18 : sprompt = "クリップボードデータをHTML-tableに変換します" & vbCrLf & _
19 : vbCrLf & vbCrLf & vbCrLf & "テーブルヘッダ 1 を入力"
20 : End If
21 :
22 : nth = InputBox(sprompt, "tabletag", "0") 'no table-header default 0
23 :
24 : If Not IsEmpty(nth) Then
25 : If nselect <> 0 Then
26 : snz = Editor.GetSelectedString(0)
27 : Editor.SetClipboard 0, snz
28 : End If
29 : scmd = batpath & " " & nth 'send 1arg to batfile
30 : Editor.ExecCommand scmd, 0
31 : End If
下記のバッチファイルに「1 か 0」を送り、バッチを実行します。
選択中の文字列がある場合には、そのデータをクリップボードに送ります
tabletag.bat
1 : @echo off
2 : rem tabletag.bat
3 : rem クリップボード内の表をHTML-tableに変換
4 : pushd %0\..
5 : call mshta_clip_out.cmd > _temp_1.txt
6 : gawk414 -v ARG1=%1 -f tabletag.awk _temp_1.txt > _temp_2.txt
7 : rem call mshta_to_clip.cmd < _temp_2.txt
8 : clip < _temp_2.txt
9 : del _temp_?.txt
10 : rem pause
クリップボードのテキストデータをテキストファイルとして生成、そのテキストをGAWKが読み、データを加工します。さらにその加工済みデータをクリップボードに戻します。
mshta_clip_out.cmd (一行書き必須)
1 : @MSHTA.EXE vbscript:Execute("s=clipboardData.getData(""text""):If Not IsNull(
s) Then CreateObject(""Scripting.FileSystemObject"").GetStandardStream(1).Wri
te(s):End If:close()")
クリップボード内のテキストデータを標準出力に送ります。
AWKプログラム
tabletag.bat / mshta_clip_out.cmd / tabletag.awk の3ファイルは同じフォルダに保存してください。また環境変数 AWKPATH にカレントディレクトリの相対パス「.\;」がないとGAWKはtabletag.awkを見つけられませんので、必ず登録してください。。
tabletag.awk
BEGIN
1 : #. awk_tabletag.awk;
2 : # tab/space で区切られた表またはcsvをtableタグに変換
3 : #. BEGIN; タグの初期化 tableタグ(開く)
4 : BEGIN {
5 : need_th = ARG1;
6 : f_c = f_t = f_h = 1;
7 : tabletag_init();
8 :
9 : #csv/tab/space+tabを簡易判別
10 : while (getline < ARGV[1] > 0) {
11 : fqc[++c] = aindex($0, ",", ar);
12 : fqt[c] = aindex($0, "\t", ar);
13 : fqh[c] = aindex($0, " \t", ar);
14 : }
15 : close(ARGV[1]);
16 :
17 : if (c > 1) {
18 : for (i = 1; i <= c - 1; i++) {
19 : if (fqc[i] != fqc[i + 1]) f_c = 0;
20 : if (fqh[i] != fqh[i + 1]) f_h = 0;
21 : if (fqt[i] != fqt[i + 1]) f_t = 0;
22 : }
23 : }
24 : else {
25 : f_c = f_t = f_h = 0;
26 : max = fqc[1];
27 : if (max < fqt[1]) max = fqt[1];
28 : if (max < fqh[1]) max = fqh[1];
29 : if (max == fqc[1]) f_c = 1;
30 : if (max == fqt[1]) f_t = 1;
31 : if (max == fqh[1]) f_h = 1;
32 : }
33 :
34 : if (f_c && fqc[1]) FS = ",";
35 : else if (f_h && fqh[1]) FS = " \t"; #優先(残スペース防止)
36 : else if (f_t && fqt[1]) FS = "\t";
37 : else ;
38 : print TB_O;
39 : }
ACTION_01
40 : #. Action; 文字列を作ってから書く
41 : {
42 : if (NR == 1 && need_th) { topen = TH_O; tclose = TH_C; }
43 : else { topen = TD_O; tclose = TD_C; }
44 :
45 : str = Tab1 TR_O "\n";
46 : for (i = 1; i <= NF; i++)
47 : str = str Tab2 topen sprintf("%s", $i) tclose "\n";
48 : print str Tab1 TR_C;
49 : }
END
50 : #. END; tableタグ(閉じる)
51 : END {
52 : print TB_C;
53 : }
tabletag_init()
54 : #. tabletag_init();tableタグを初期化
55 : function tabletag_init() {
56 : TB_O = "<table class=\"tbl1\">";
57 : TB_C = "</table>";
58 : TH_O = "<th>";
59 : TH_C = "</th>";
60 : TR_O = "<tr>";
61 : TR_C = "</tr>";
62 : TD_O = "<td>";
63 : TD_C = "</td>"
64 : Tab1 = "\t";
65 : Tab2 = "\t\t";
66 : }
aindex()
67 : #. aindexa();index()拡張
68 : # 戻り値: 発見した個数
69 : # str: 文字列
70 : # find: 検索文字列
71 : # apos: 配列(全位置)
72 : function aindex(str, find, apos, pos, tpos, freq) {
73 : freq = 0;
74 : delete apos;
75 : do {
76 : if (pos = index(str, find)) {
77 : tpos += pos;
78 : apos[++freq] = tpos;
79 : str = substr(str, pos + 1);
80 : }
81 : } while (pos)
82 : return freq;
83 : }
文字列やファイルから、特定の文字(文字列)の出現回数を数える方法はいくつかあります。AWK 特有の数え方で split()
を使用するものが一般的?ですが、今回は、こんな関数便利かもよ、と自作関数 aindex()
を利用してみました。出現頻度が高いなら split($0, ar, ",") - 1
の方が速いのですが。
空白区切りの表(デフォルトFS)で先頭・末尾データが空("")であった場合、AWKはそのレコードを正しく分割できません。デフォルトFS 即ち FS=" "(スペース1文字) を指定すると、分割前に前後の空白を除去する仕様みたいです。split()も同じ仕様なのか、区切り文字をスペース1文字にすると、先頭の空データを無視してしまいます。上記の特定文字の出現回数を調べる利用法については要注意です。