Deno で簡単な重複行削除スクリプトを書いた
ファイルの重複行削除がしたかったのでスクリプトを書こうと思ったのですが、せっかくだし Deno で書いてみることにしました。
https://github.com/ushumpei/scripts/blob/main/remove_duplicate_lines.ts
import { iter } from "https://deno.land/std@0.93.0/io/util.ts"; const N = Deno.env.get("NEWLINE") || "\n"; export type M = { b: boolean; d: string[]; h: { [k: string]: boolean }; }; const i = Deno.args[0]; const o = Deno.args[1]; const f: Deno.File = Deno.openSync(i, { read: true }); const m: M = { d: [], h: {}, b: false }; const t: string = await Deno.makeTempFile(); let r = ""; for await (const ck of iter(f)) { const ls = (r + new TextDecoder().decode(ck)).split(N); r = ls[ls.length - 1]; const ot = ls .slice(0, -1) .reduce((_m: M, l: string) => { if (!_m.h[l]) { _m.h[l] = true; _m.d.push(l); } return _m; }, m) .d.join(N); if (ot.length === 0) continue; const of = new TextEncoder().encode(m.b ? N + ot : ot); Deno.writeFileSync(t, of, { append: true }); m.d = []; m.b = true; } f.close(); Deno.copyFileSync(t, o);
github にあげていて、こんな感じで URL 指定でも実行できます。
$ deno run --allow-env --allow-read --allow-write \ > https://raw.githubusercontent.com/ushumpei/scripts/main/remove_duplicate_lines.ts \ > 入力ファイル名 \ > 出力ファイル名
感想
groovy
のようにライブラリのインポート含めてスクリプトが一枚のファイルで完結するので、結構楽でいいです。しかも URL 指定でインポートできるのでより手軽。なので書くときにインポートするものをちゃんと精査しないといけないと思います。--allow-net
などオプションで権限が指定できるので、その辺もしっかり吟味していきたいです。(権限つけ忘れた時のエラー文がわかりやすいのも良い感じ)- 書いたスクリプトで宣言している変数名は一文字とかばかりなのですが、なんかテンション上がって極力短くしてみました。楽しかった。
- 環境変数による改行コードの指定は未テストで、いらないんじゃないかなーと思っています。
--allow-env
も消せるしそうしたい気がしてきた。 - メモリに一気に乗せないように書いたつもりだけどどうなんだろう。
- 既出行を格納しているオブジェクトが巨大になって死ぬとかありそう。
- あと
copyFileSync
は中身をみていないけどちょろちょろコピーしてくれるのだろうか? - あとこれ
TransformStream
で描き直したい。
Deno
のvscode
拡張入れた後上手く設定できてなくてcannot find name Deno
とか言われてたけどコマンドパレットからDeno: Initialize Workspace Configuration
実行したらなんか上手くいった。- 無限インポートループとかどうなるんだろうか。
- https://doc.deno.land/builtin/stable 見て書いた。
- Deno Deploy はまだちゃんと触っていない、リクエスト処理は
fetch
イベントのハンドラー書いてやるみたいだけど、ローカルだと発火しなくてちょっと手間取った、なんか公開してくださっているライブラリ入れたら動いた。https://deno.land/x/fetch_event_adapter/listen.ts