LoginSignup
7
3

More than 5 years have passed since last update.

試しに Deno で CSV から SQL 文を生成する処理を実装してみる

Posted at

表題のよくありがちな簡単な作業があったので、 Deno を触ってみるのにいい題材かなと思い使ってみました。

Deno のキャッチアップ

Deno について知っていることと、今後への期待
Deno

VSCode で Deno を書く準備

こちらの denoの標準ライブラリをVS Codeでいい感じに補完するためにやった作業 という記事を参考に、 deno --types で生成できる標準モジュールの型定義と、~/.deno/deps以下にDLされる外部モジュールへパスを通して補完するようになりました。

また、上記記事の方がこの設定を生成するツール denoinit というのも作っています。

実装してみる

とりあえず何を使ったらいいかみてみました

コマンドの引数を取得する

args を使う方法

args.ts
import { args } from "deno";
console.log(args);
$ deno args.ts param1 param2
[ "args.ts", "param1", "param2" ]

ファイルの内容を取得する

open を使う方法

open.ts
import { args, copy, open, stdout } from "deno";

(async () => {
  const file = await open(args[1]);
  await copy(stdout, file);
  file.close();
})();

readFile を使う方法

readFile.ts
import { args, readFile, stdout } from "deno";

(async () => {
  const data = await readFile(args[1]);
  stdout.write(data);
})();
$ deno open.ts example.csv
1,a
2,b
$ deno readFile.ts example.csv
1,a
2,b

他のコマンドを実行する

対象の CSV が Shift_JIS なので文字コードを変換したかったのですが、 iconv 的なモジュールはないようで、自作したくないので、とりあえず Linux コマンドの iconv を実行することにしました。

run を使って子プロセスを起動するようです。

iconv.ts
import { args, run, stdout } from "deno";

(async () => {
  const process = run({
    args: ["iconv", "-f", "sjis", "-t", "utf8", args[1]],
    stdout: "piped"
  });
  stdout.write(await process.output());
  process.close();
})();

実行する際に子プロセス実行許可オプションを付けます。

$ deno --allow-run iconv.ts example.csv
1,a,あ
2,b,い

CSV をパースする

deno-fnparse
どうやら年末にもくもく会があったみたいですが、ちょうど CSV パーサが作られていてよかったです。

parse.ts
import { args, run } from "deno";
import { parseCsv } from "https://denopkg.com/hashrock/deno-fnparse/parsers/csv.ts";

(async () => {
  const process = run({
    args: ["iconv", "-f", "sjis", "-t", "utf8", args[1]],
    stdout: "piped"
  });
  const csv = new TextDecoder().decode(await process.output());
  process.close();

  const rows = parseCsv(csv);
  console.log(rows);
})();
$ deno --allow-run parse.ts example.csv
[ [ "1", "a", "あ" ], [ "2", "b", "い" ] ]

一通り書いたので実行可能にする

Shebang を付ける

convert.ts
#!/usr/bin/env deno --allow-run

import { args, run, stdout } from "deno";
import { parseCsv } from "https://denopkg.com/hashrock/deno-fnparse/parsers/csv.ts";

(async () => {
  const process = run({
    args: ["iconv", "-f", "sjis", "-t", "utf8", args[1]],
    stdout: "piped"
  });
  const csv = new TextDecoder().decode(await process.output());
  process.close();

  const rows = parseCsv(csv) as string[][];

  const table = args[1].slice(0, -4);
  const encoder = new TextEncoder();
  rows.forEach(row => {
    stdout.write(
      encoder.encode(`INSERT INTO ${table} VALUES ('${row.join("', '")}');\n`)
    );
  });
})();
$ chmod +x convert.ts
$ ./convert.ts example.csv
INSERT INTO examples VALUES ('1', 'a', 'あ');
INSERT INTO examples VALUES ('2', 'b', 'い');

以上です。
下記のようにディスカッションされていますが、この手の変換処理は本当は Reader / Writer ベースで処理を書いた方が望ましいと思うので宿題にしようと思います。

今回のソースコード

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3