Node.js: テキストの処理 (1)
TSVファイルの処理
Node.js で TSV (タブ区切りのテキスト) を出力したり、
TSV ファイルを読んで処理したりする話です。
プログラムの処理結果をリダイレクトでテキストファイルに保存したり、
ファイルを読んで処理したりします。
カンマ区切りのテキスト (CSV) もほぼ同じように処理できます。
JavaScript テキストデータを読んで処理
その1: ファイルリストを TSV で出力する
/* node TestNodejs_tsv_filelist1.js (ディレクトリ名) node TestNodejs_tsv_filelist1.js node TestNodejs_tsv_filelist1.js /nodejs ・指定ディレクトリのファイルリストをTSV(タブ区切りのテキスト) で出力する。 ・出力TSVのフォーマット filename size time ディレクトリは size = -1 time は更新時刻の long値 */ const FS = require("fs"); const PATH = require("path"); let dir = process.argv[2]; if (!dir){ dir = "."; } const list = FS.readdirSync(dir); for (const name of list){ try{ const path = PATH.join(dir, name); const st = FS.statSync(path); const size = (st.isDirectory(path) ? -1 : st.size); console.log("%s\t%s\t%s", name, size, st.mtimeMs); } catch(e){ //error への出力はリダイレクトでファイルに保存されない。 console.error("err:"+e); //console.error("err:"+e.stack); //エラーの発生箇所を表示 } }
その2: TSV ファイルを読んでテキストを整形する
/* node TestNodejs_tsv_filelist2.js (TSVファイル名) node TestNodejs_tsv_filelist2.js tmp.txt ・TSVのファイルリストを読んで、テキストを整形して表示する。 TestNodejs_tsv_filelist1.js で出力した TSVファイルを使う。 */ const FS = require("fs"); const text = FS.readFileSync(process.argv[2], { encoding:"utf8" }); //TSV を 2重配列に分割する const mat = text.split(/\r\n|\n|\r/).map( s => s.split("\t")); //TSVの最後の行が空行なので除去する mat.pop(); for (const array of mat){ try{ const time = parseInt(array[2]); const date = createDateString( new Date(time)); const size = createSizeString(array[1]); const name = array[0]; console.log("%s %s %s", date, size.padStart(12), name); } catch(e){ console.error("err:"+e); } } //サイズの文字列を作る。 function createSizeString(size){ return (size < 0 ? "dir" : size); } //日付の文字列を作る。YYYY/MM/DD hh:mm:ss function createDateString(date){ const s = date.getFullYear() + "/" + ("0" + (date.getMonth() + 1)).slice(-2) + "/" + ("0" + date.getDate()).slice(-2) + " " + ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2) + ":" + ("0" + date.getSeconds()).slice(-2); return s; }
実行
node TestNodejs_tsv_filelist1.js > tmp.txt node TestNodejs_tsv_filelist2.js tmp.txt
その3: TSV ファイルを読んで指定の列でソートする
/* node TestNodejs_tsv_sort1.js (TSVファイル名) (オプション) node TestNodejs_tsv_sort1.js tmp.txt index=1 type=int ◎オプション ・index=(数値) 省略した場合は 0。 ソートする列のインデックス値、0から数える。 ・type=string, int 省略した場合は string string : 文字列で比較 int : 整数で比較 */ const FS = require("fs"); const filepath = process.argv[2]; const options = parseOption(process.argv, 3); const sortIndex = parseInt( getOption(options, "index", 0)); const sortType = getOption(options, "type", "string"); //ソート方法のテーブル const sortTable = { "string" : (a, b) => a[sortIndex] > b[sortIndex] ? 1 : -1, "int" : (a, b) => parseInt(a[sortIndex]) - parseInt(b[sortIndex]), }; const text = FS.readFileSync(filepath, { encoding:"utf8" }); //TSV を 2重配列に分割する。空行は除去する(途中の空行も除去する例)。 const mat = text.split(/\r\n|\n|\r/).filter( s => s ).map( s => s.split("\t")); //並べ替える mat.sort( sortTable[sortType]); //結果を出力する console.log( mat.map( a => a.join("\t")).join("\n")); //コマンドラインのオプションを連想配列 {} にパースする function parseOption(argv, startIndex){ const map = {}; for (let i=startIndex; i < argv.length; i++){ const a = argv[i].split("="); const key = a[0]; map[key] = a[1]; } return map; } function getOption(options, key, defaultValue){ const value = options[key]; return (value ? value : defaultValue); }
実行例
◎ファイル名でソートする node TestNodejs_tsv_filelist1.js > tmp.txt node TestNodejs_tsv_sort1.js tmp.txt > tmp2.txt node TestNodejs_tsv_filelist2.js tmp2.txt ◎ファイルサイズでソートする node TestNodejs_tsv_filelist1.js > tmp.txt node TestNodejs_tsv_sort1.js tmp.txt index=1 type=int > tmp2.txt node TestNodejs_tsv_filelist2.js tmp2.txt ◎日付でソートする node TestNodejs_tsv_filelist1.js > tmp.txt node TestNodejs_tsv_sort1.js tmp.txt index=2 type=int > tmp2.txt node TestNodejs_tsv_filelist2.js tmp2.txt
関連
- TestJS_location_search01.html
コマンドラインの引数処理に関連して、 URL の CGI パラメータを取り出すサンプル。
JavaScript: 区切り文字で分割する
JSON で出力する
TSV ファイルの代わりに JSON で出力したり、JSON
ファイルを読んで処理したりすることもできます。
単純なリストや 2重配列では間に合わないデータに適しています。
JavaScript: JSON シリアライズ
ファイルリストを JSON で出力する
/* node TestNodejs_json_filelist1.js (ディレクトリ名) node TestNodejs_json_filelist1.js node TestNodejs_json_filelist1.js /nodejs ・指定ディレクトリのファイルリストを JSON で出力する。 ディレクトリは size = -1 time は更新時刻の long値 */ const FS = require("fs"); const PATH = require("path"); let dir = process.argv[2]; if (!dir){ dir = "."; } const list = FS.readdirSync(dir); const array = []; for (const name of list){ try{ const path = PATH.join(dir, name); const st = FS.statSync(path); const size = (st.isDirectory(path) ? -1 : st.size); const map = { "name": name, "size": size, "time" : st.mtimeMs }; array.push(map); } catch(e){ console.error("err:"+e); } } //JSON文字列を作る const json = JSON.stringify(array); console.log(json);
JSON テキストをオブジェクトに戻す
テキストファイルを読んで JSON.parse(text) でオブジェクトに戻します。
// たった 1行で簡単に Object に戻せます。 let obj = JSON.parse(text);
いろいろ
パイプ処理
上のサンプルでは、処理結果を 1度リダイレクトで
テキストファイルに保存して、
次のコマンドプログラムでテキストファイルを読み直して処理しています。
これとは別にファイル保存を使わず、
処理結果を直接次のコマンドの入力データとして渡す処理方法もあります (パイプ処理)。
パイプ処理はコマンドラインの処理で多用されます。
Wikipedia: パイプ (コンピュータ)