Node.js脚本集锦
Posted stalendp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js脚本集锦相关的知识,希望对你有一定的参考价值。
运行命令行(TODO,日志输出需要改进)
const proc = require('child_process');
var x = function(cmd, showCmd)
console.log('>> ' + cmd);
return new Promise((resolve, reject) =>
var p = proc.exec(cmd, maxBuffer: 100 * 1024 * 1024, (err, stdout, stderr) =>
if(err)
console.error(err);
reject(err);
else if(stderr)
console.error(stderr);
reject(stdout);
else
resolve(stdout);
);
);
;
(async function()
await x("ping -t 3 baidu.com");
var s = await x('ls');
console.log(s);
)();
一个解析数独游戏的程序:
var solverHelper = function(_solver, _type, _sidx)
var solver = _solver;
var type = _type;
var ess = [];
let si, sj;
if(type == 0) // 方块
si = Math.floor(_sidx / 3) * 3;
sj = _sidx % 3 * 3;
for(let i=0; i<3; i++)
for(let j=0; j<3; j++)
ess.push(solver.getES(si + i, sj + j));
else if(type == 1) // 行
si = _sidx;
sj = 0;
for(let j=0; j<9; j++)
ess.push(solver.getES(si, j));
else if(type==2) // 列
si = 0;
sj = _sidx;
for(let i=0; i<9; i++)
ess.push(solver.getES(i, sj));
return
updateVal: (val) =>
for(let i=0; i<9; i++)
ess[i].updateVal(val);
,
evaluate: () =>
for(let v=0; v<9; v++)
let testV = 1 << v;
let cnt = 0;
let ii = 0;
for(let i=0; i<9; i++)
if((ess[i].Magic & testV) > 0)
cnt ++;
ii = i;
if(cnt == 1 && !ess[ii].isOK)
ess[ii].setVal(v + 1);
if(cnt == 0)
return false;
return true;
,
printR : () =>
var rt = [];
if(type == 0)
rt.push(`type: square - ($si, $sj)\\n==========\\n`);
for(let i=0; i<9; i++)
rt.push(ess[i].Val);
rt.push(",");
if((i+1)%3 == 0)
rt.push("\\n");
else
rt.push(`type: $type==1 ? "row" : "column" - $si,$sj\\n==========\\n`);
var s = type==1 ? "," : "\\n";
for(let i=0; i<9; i++)
rt.push(ess[i].Val);
rt.push(s);
rt.push("\\n");
console.log(rt.join(""));
,
toString: function()
return `$type==0 ? "square" : type==1? "row" : "column" :: ($si, $sj)`;
;
var elemSolver = function (_solver, _i, _j)
var s = _solver;
var i = _i;
var j = _j;
var n = -1; // 可能个数
var val;
var magic;
return
ensureInit : function ()
if(n<0)
val = s.getE(i, j);
if(val != 0) // 默认值
magic = 1 << (val-1);
n = 1;
s.notify(this);
else
magic = 0x1FF;
n = 9;
,
setVal : function(_val)
val = _val;
magic = 1 << (val-1);
n = 1;
s.notify(this);
,
init: function()
this.ensureInit();
,
updateVal: function(_val)
if(!_val || n == 1) // 已经完成
return;
this.ensureInit();
magic &= ~(1<<(_val-1));
,
refreshN: function(isInit)
if(n == 1)
if(isInit)
s.notify(this);
return true;
// 重新计算n
let vv = 0;
n = 0;
for(let x = 0; x < 9; x ++)
if((magic & (1<<x)) > 0)
vv = x + 1;
n++;
if(n==1)
val = vv;
s.notify(this); // 通知完成
return n > 0;
,
possibleVals : function()
var rt = [];
for(let x = 0; x < 9; x ++)
if((magic & (1<<x)) > 0)
rt.push(x+1);
return rt;
,
get I() return i,
get J() return j,
get N() return n,
get isOK() return n == 1;,
get Val() return n == 1 ? val : '_',
get Magic() return magic; ,
toString : function() return `($i,$j)_$n_$this.possibleVals().join(",")`;,
toString2() return `$this.Val.$n==1? "_" : n.$n==1 ? "___" : magic.toString(16).padStart(3, '0')`;,
serilize: function()
return (val & 0xF) | ((n&0xF) << 4) | ((i&0xF)<<8)|((j&0xF)<<12) |((magic & 0x1FF) << 16);
,
deserilize: function(v)
val = v&0xF;
n = (v >> 4) & 0xF;
i = (v>>8) &0xF;
j = (v >> 12) & 0xF;
magic = (v>>16) &0x1FF;
,
;
var solver = (function()
var m;
var ess = [];
var shs = [];
var solvedNum = 0;
var tryQueue = [];
return
_init : function(_m)
m = _m;
for(let i=0; i<9; i++)
for (let j=0; j<9; j++)
ess.push(elemSolver(this, i, j));
for(let t=0; t<3; t++)
let tmp = [];
for(let i=0; i<9; i++)
tmp.push(solverHelper(this, t, i));
shs.push(tmp);
// 初始化
for(let i=0; i<81; i++)
ess[i].init();
// this.printR(`init => $solvedNum`, true);
,
solve: function(_m)
// 重置
ess = [];
shs = [];
solvedNum = 0;
tryQueue = [];
// 处理
this._init(_m);
if(this._doLogic())
this.printR();
else
console.log("No Result!");
// step 2. do guess
,
doTry : function()
// 找到最小范围的
let smallest = 10;
let sel;
for(let i=0; i<81; i++)
let tmp = ess[i];
if(!tmp.isOK)
if(tmp.N < smallest)
smallest = tmp.N;
sel = tmp;
if(smallest == 2)
break;
this.saveResult();
var ps = sel.possibleVals();
var rt = true;
for(let i=0; i<ps.length; i++)
var v = ps[i];
this.printR(`Before Try @@ $tryQueue.length - $sel.toString() :: $v `, true);
sel.setVal(v);
if(this._doLogic())
return true;
this.restoreResult();
this.popResult();
return false;
,
saveResult: function()
var q =[];
for(let i=0; i<81; i++)
q.push(ess[i].serilize());
tryQueue.push(q);
,
restoreResult: function()
var q = tryQueue.length > 0 ? tryQueue[tryQueue.length - 1] : undefined;
solvedNum = 0;
for(let i=0; i<81; i++)
let e = ess[i];
e.deserilize(q[i]);
if(e.isOK)
solvedNum++;
,
popResult: function()
tryQueue.pop();
,
_doLogic: function()
let tmpNum;
while(tmpNum != solvedNum && solvedNum < 81)
// 1. step
while(tmpNum != solvedNum && solvedNum < 81)
tmpNum = solvedNum;
for(let i=0; i < 81; i++)
if(!ess[i].refreshN())
console.log(`[Try] 1 Failed at :$ess[i].toString()`);
return false;
if(solvedNum < 81)
// 2. step evaluate
for(let t=0; t < 3; t++)
for(let i=0; i<9; i++)
if(!shs[t][i].evaluate())
console.log(`[Try] 2 Failed at : $shs[t][i].toString()`);
return false;
if(solvedNum!=81)
return this.doTry();
else
return true;
,
getE: (i, j) =>
return m[i * 9 + j];
,
getES : (i, j) =>
return ess[i * 9 + j];
,
notify: (es) =>
if(es.N != 1)
return;
solvedNum ++;
if(solvedNum < 81)
let i = es.I;
let j = es.J;
let val = es.Val;
shs[0][Math.floor(i/3)*3 + Math.floor(j/3)].updateVal(val);
shs[1][i].updateVal(val);
shs[2][j].updateVal(val);
else
solvedNum = 81;
,
printR : (msg, level)=>
if(msg)
console.log(msg + "\\n");
if(!level)
level = 0;
let rt = [`solvedNum: $solvedNum \\n`];
if(level == 0)
for(let i=0; i<9; i++)
for (let j=0; j<9; j++)
rt.push(ess[i*9 + j].Val);
rt.push(",");
if((j+1)%3 == 0)
rt.push(" ");
rt.push("\\n");
if((i+1)%3==0)
rt.push("\\n");
else if(level == 1)
for(let i=0; i<9; i++)
for (let j=0; j<9; j++)
rt.push(ess[i*9 + j].toString2());
rt.push(" ");
if((j+1)%3 == 0)
rt.push(" ");
rt.push("\\n");
if((i+1)%3==0)
rt.push("\\n");
console.log(rt.join(""));
,
test: function()
// this.saveResult();
// this.restoreResult();
// this.printR("", true);
,
)();
solver.solve([
//
3,9,0, 2,0,0, 8,0,0,
0,0,0, 7,0,0, 0,2,9,
7,0,0, 3,0,0, 0,5,0,
//
0,0,0, 0,0,0, 9,3,0,
0,0,0, 4,1,2, 0,0,0,
0,5,6, 0,0,0, 0,0,0,
//
0,7,0, 0,0,4, 0,0,2,
4,1,0, 0,0,6, 0,0,0,
0,0,3, 0,0,7, 0,8,4,
]);
solver.solve([
//
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
//
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
//
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
0,0,0, 0,0,0, 0,0,0,
]);
// 用jar的打包方式创建aar文件
var fs = require('fs');
var path = require('path');
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function jar(fn)
var cmd = 'jar cvf ' + fn + ".aar -C " + fn + " " + fn + "/*";
// const stdout, stderr = await exec(cmd);
// console.log('stdout:', stdout);
// console.log('stderr:', stderr);
console.log(cmd);
var dirs = p => fs.readdirSync(p).filter(f=> fs.statSync(path.join(p,f)).isDirectory());
(function()
var files = dirs('.');
files.forEach(function(f)
if(fs.statSync(f).isDirectory())
var fn = path.basename(f);
if(fn!="HeroesArena" && fn!="lib_source")
// create jar
jar(fn);
);
)();
// 生成Eclipse工程。
// 运行环境,安卓node.js, 并安装node插件:
// npm install unzip-stream --save
var fs = require('fs');
var path = require('path');
var unzip = require('unzip-stream');
var dirs = p => fs.readdirSync(p).filter(f=> fs.statSync(path.join(p,f)).isDirectory());
var basedir = path.join("..", "Assets", "Plugins", "android");
// 一些要处理的aar文件
var aars = ["appcompat-v7-24.1.1", "cardview-v7-24.1.1", "design-24.1.1", "firebase-common-10.2.1",
"firebase-iid-10.2.1", "firebase-messaging-10.2.1", "installreferrer-1.0", "play-services-basement-10.2.1",
"play-services-tasks-10.2.1", "recyclerview-v7-24.1.1", "support-v4-24.1.1", "support-vector-drawable-24.1.1"
];
aars.forEach(function(aarName)
var aarFile = path.join(basedir, aarName + ".aar");
var aarPath = path.join("..", "AndroidBuild", aarName);
// 解压aar文件到AndroidBuild目录下
var stream = fs.createReadStream(aarFile).pipe(unzip.Extract( path: aarPath ));
stream.on("close", function()
var libPath = path.join(aarPath, "libs");
var libFile = path.join(aarPath, "classes.jar");
if(!fs.existsSync(libPath))
fs.mkdirSync(libPath);
// 处理classes.jar文件,改个名字,并移动到libs目录下
if(fs.existsSync(libFile))
fs.renameSync(libFile, path.join(libPath, aarName + ".jar"));
// 为了编译通过,需要创建src目录
var srcPath = path.join(aarPath, "src");
if(!fs.existsSync(srcPath))
fs.mkdirSync(srcPath);
console.log(aarName);
);
);
(function()
var abp = path.join("..", "AndroidBuild");
var files = dirs(abp);
files.forEach(function(f)
var ff = path.join(abp, f);
if(fs.statSync(ff).isDirectory())
var fn = path.basename(ff);
if(fn=="HeroesArena" || fn=="lib_source")
var srcPath = path.join(ff, "src");
if(!fs.existsSync(srcPath))
fs.mkdirSync(srcPath);
);
)();
一个日志解析工具
var fs = require('fs');
var path = require('path');
var DID = 149496940;
var lr = require('readline').createInterface( // 一行一行读取文件
input: require('fs').createReadStream('sample.log')
);
//https://stackoverflow.com/questions/30452263/is-there-a-mechanism-to-loop-x-times-in-es6-ecmascript-6-without-mutable-varia
const times = n => f => // 循环函数定义,参考下面的调用
let iter = i =>
if (i === n) return
f (i)
iter (i + 1)
return iter (0)
// 一些正则表达式的使用方法
//182.61.120.11 ha.mobaonline.com - [27/Jan/2018:23:48:30 -0800] "GET /pixel.jpg?client=moba&os=2&type=onWindowFocusChanged_1&is50mClient=1&hd=0&version=1.2.9.184&appVersion=1.2.9&obbVersion=128&channel=googleplay&uuid=ffffffff8b74d89eddf7ae8e0033c587&user_id=14660192&newbie=0&sn=0&f=unity HTTP/1.0" 200 119 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; US699 Build/MMB29M)" "-" "0.229" "-" "-" "-" "182.61.33.150" "182.61.33.150, 113.134.222.207, 113.134.222.207, 182.61.33.150, 182.61.120.11"
var reg = /type=([^&]+).*?user_id=(\\d+)/i;
var regTime = /ReportOnlineTime_(.*)/i;
var regTimeAll = /(ReportOnlineTime|onWindowFocusChanged_0|OnlineTime|RoomConnected|ProxyConnect|StorageFull|CErrorDLCode|CErrorCheckDstHash|CErrorDL4Times|CErrorDLOpenFile)_.*/i;
var User = function(_id)
const CNT = 10;
var id = _id;
var duration = 0;
var queue = new Array(CNT);
var replaced = [];
var count = 0;
var fixQueue = function()
var tmp = [];
var start = count > CNT ? count - CNT : 0;
var n = count > CNT ? 10 : count;
times(n) (i => // 循环函数的调用
var d = queue[start%CNT];
tmp.push(d.replace(regTimeAll, "$1"));
start++;
);
queue = tmp;
;
return
get ID() // getter函数
return id;
,
parse: function(d)
var m = regTime.exec(d);
if(m)
var tt = parseInt(m[1]);
if(duration < tt)
duration = tt;
queue[count%CNT] = d;
count++;
,
analysis: function(us)
fixQueue();
queue.forEach(e =>
replaced.push(us.getIdx(e));
);
,
print: function()
console.log(id + "->" + replaced.join(","));
;
;
var cc = 0;
var Users = function()
var us = [];
var dict = ; // Dictionary的用法
var dCnt = 0;
return
parse: function(uid, data)
var u = us[uid];
if(u == null)
cc++;
u = new User(uid);
us[uid] = u;
u.parse(data);
,
getIdx: function(elm)
var rt = dict[elm];
if(rt==null)
rt = dCnt;
dict[elm] = dCnt;
dCnt++;
return rt;
,
print: function()
us.forEach(u =>
u.analysis(this);
);
us.forEach(u =>
u.print();
);
console.log(dict);
;
;
var DebugUser = function(_uid)
var uid = _uid;
var ds = [];
return
parse : (id, d) =>
if(id == uid)
ds.push(d);
,
print : v =>
console.log("================== " + uid + " ==============");
ds.forEach(elm =>
// console.log(elm);
);
;
;
//======================= MAIN Start =========================
var du = new DebugUser(DID);
var us = new Users();
var t0 = new Date().getTime();
lr.on('line', line =>
var m = reg.exec(line);
if(m)
var id = m[2];
var dd = m[1];
us.parse(id, dd);
du.parse(id, dd);
).on('close', v =>
us.print();
du.print();
var t1 = new Date().getTime();
console.log("Finished by " + ((t1 - t0)/1000.0) + " seconds.") // 计算运行时间
);
//======================= MAIN End =========================
处理ios的崩溃日志的工具,原理参考 Understanding and Analyzing Application Crash Reports
其实就是atos工具的使用,目前添加了对文件的处理。输入是 heroesarena.app.dSYM和crash.log,输出是crash_parsed.log
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var stream = require('stream');
// https://github.com/abbr/deasync
// npm install deasync
var deasync = require('deasync');
var cp = require('child_process');
const es = require('event-stream');
var cmdPre = "atos -arch arm64 -o heroesarena.app.dSYM/Contents/Resources/DWARF/heroesarena -l";
var reg = /heroesarena\\s+(0x[^\\s]+)\\s+(0x[^\\s]+)/i;
var lr = require('readline').createInterface(
input: fs.createReadStream('crash.log')
);
var exec = deasync(cp.exec);
//0 heroesarena 0x0000000100ed3514 0x100040000 + 15283476
var reg2 = /^\\d+\\s+heroesarena\\s+((0x[^\\s]+)\\s+(0x[^\\s]+).*)$/i;
var reg3 = /(0x[^\\s]+\\s+0x[^\\s]+.*$)/i;
var parse = function(dict) // convert the file
fs.createReadStream('crash.log')
.pipe(es.split())
.pipe(es.mapSync(l =>
var m = reg2.exec(l);
if(m)
var t1 = dict[m[3]];
if(t1!=null)
var t2 = t1[m[2]];
if(t2!=null)
l = l.replace(reg3, t2);
return l;
))
.pipe(es.join('\\n'))
.pipe(fs.createWriteStream('crash_parsed.log'))
.on('close', () =>
console.log('Done!');
);
;
var dict = [];
lr.on('line', line =>
var m = reg.exec(line);
if(m)
var addr1 = m[2];
var offsets = dict[addr1];
if(offsets == null)
offsets = [];
dict[addr1] = offsets;
var addr2 = m[1];
if(offsets[addr2] == null)
offsets[addr2] = addr2;
).on('close', v =>
Object.keys(dict).forEach(adr1 =>
var adr2s = dict[adr1];
var keys = Object.keys(adr2s).map(x => x);
var rst = exec(`$cmdPre $adr1 $keys.join(' ')`); // 这里的写法,类似于stringFormat
var lines = rst.split(/\\r?\\n/);
for(var i=0; i<keys.length; i++)
adr2s[keys[i]] = lines[i];
parse(dict);
);
);
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var stream = require('stream');
var crypto = require('crypto');
var projDir = "D:\\\\_Moba\\\\Working\\\\1.7"; // 设置工程文件夹!!
var baseDir = path.join(projDir, "\\\\Assets\\\\BuildOnlyAssets");
var okFiles = ;
var okFile2 = ;
var md5 = str => crypto.createHash('md5').update(str).digest('hex'); // MD5相关算法
var tmpDirs = [];
var reg = /([^\\.]+)\\..+$/i;
var reg2 = /(?:[^\\\\/]+[\\\\/])*(([^\\.]+)(\\..+)?)$/gi;
// 遍历文件夹,并计算MD5
var myIter = function(cur, dirs)
// console.log(cur);
var full = path.join(baseDir, cur);
fs.readdirSync(full).forEach(f =>
if(!f.startsWith("."))
var tmp = path.join(cur, f);
if(fs.statSync(path.join(baseDir, tmp)).isDirectory())
dirs.push(tmp);
else // 计算MD5
if(!f.endsWith(".meta") )
var fn = `SuI9_hero_project_2014/$tmp.toLowerCase().replace(/\\\\/gi, "/").replace(reg, "$1").assets`;
var m = md5(fn); // MD5的用法
okFiles[m] = tmp;
okFile2[tmp.replace(reg2, "$1")] = m;
);
tmpDirs.push(".");
while(tmpDirs.length > 0) // 处理所有的文件
myIter(tmpDirs.shift(), tmpDirs); // queue的用法
// 把文件大小,显示成合适的大小
var fmtSize = function(size) // 格式化文件大小的显示
var tn = ['B', 'K', 'M', 'G', 'T'];
var t = 0;
while(size > 1024)
size /= 1024;
t++;
return `$size.toFixed(2)$tn[t]`; // float保留两位小数
var jsonfile = "fileList4.json";
if(fs.existsSync(jsonfile)) // 打印一些下载包大小
var lr = require('readline').createInterface( // 一行一行读取文件
input: require('fs').createReadStream(jsonfile)
);
var reg = /"f":"(\\d+)".+"o":(\\d)/i;
var size1=0, size2=0;
lr.on("line", line =>
var m = reg.exec(line);
if(m)
if(m[2]==1)
size2 += parseInt(m[1]); // 把字符串转化为int
else
size1 += parseInt(m[1]);
else
// console.log(line);
).on("close", line =>
console.log(`required_Size: $fmtSize(size1), optional_Size: $fmtSize(size2)`);
);
console.log("输入查询的文件:");
var rl = require('readline').createInterface(
input:process.stdin,
output:process.stdout
);
rl.on('line', function(line)
if(line.length<=0)
return;
if(line.startsWith(">>"))
var reg = />>\\s*([^\\.]+)(?:\\.(.*))?$/gi;
var fn = line.toLowerCase().replace(/\\\\/gi, "/");
var m = (reg).exec(fn);
if(m[2]) // 有后缀
if(/(?:bnk)|(?:wen)|(?:ddx)|(?:ddv)|(?:txt)/gi.test(m[2]))
fn = fn.replace(reg, "SuI9_hero_project_2014/$1.$2")
else
fn = fn.replace(reg, "SuI9_hero_project_2014/$1.assets");
else
fn = fn.replace(reg, "SuI9_hero_project_2014/$1.assets");
var m = md5(fn);
console.log(`$fn => $m`);
else
var dict = okFiles;
var reg = /(?:[^\\\\/]+[\\\\/])*(([^\\.]+)(\\..+)?)$/gi;
var m = reg.exec(line);
if(!m)
return;
if(!m[3] || m[3] == ".ddx")
dict = okFiles;
line = m[2];
else
dict = okFile2;
line = m[1];
// console.log(nn);
var realName = dict[line];
if(realName)
console.log(realName);
else
console.log("Not found! ");
console.log();
);
rl.on('close', function()
console.log('bye bye');
process.exit(0);
);
// 一些测试
// var lr = require('readline').createInterface(
// input: fs.createReadStream('patch.json')
// );
// var reg = /".":"(.\\/[^\\"]+)"/i;
// var dict = [];
// lr.on('line', line => //
// var m = reg.exec(line);
// if(m)
// var fn = m[1];
// var realName = okFiles[fn];
// if(!realName)
// console.log("not found ==> " + fn);
// else
// console.log(realName);
//
//
// ).on('close', v =>
// console.log("Done!!");
// );
通过adb shell列出文件内容
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
function exec(cmd, parameter, callback)
var proc = require('child_process').exec(cmd);
var content = "";
proc.stdout.setEncoding('utf8');
proc.stdout.on('data', function (chunk)
content += chunk;
);
proc.stdout.on('end', function ()
callback(content);
);
proc.stdin.write(parameter);
exec("adb shell", "cd /sdcard/Android/data/com.ucool.heroesarena/patch6 && find . -type f \\\\( -name '*.ddx' -o -name '*.bnk' \\\\) -print0 | xargs -0 ls -al && exit \\r\\n", str =>
console.log(str);
);
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var proc = require('child_process');
var baseDir = "D:\\\\_Moba\\\\Working\\\\client_1.5";
baseDir = path.join(baseDir, "Assets\\\\BuildOnlyAssets");
// Promise的用法参考 http://exploringjs.com/es6/ch_promises.html
var exec = function(cmd)
return new Promise((resolve, reject) =>
var p = proc.exec(cmd, maxBuffer: 100 * 1024 * 1024, (err, stdout, stderr) =>
if(err)
reject(err);
else
resolve(stdout);
);
);
var jsonName = "fileList4.json";
var delJson = function()
if(fs.existsSync(jsonName))
fs.unlinkSync(jsonName);
;
// "a":"0/013952985da37eff54db7669b280106b.ddx","b":"f1698cba18bc707705f48d96659e5bc7","c":"13213","d":"1.0.84.1077","e":"1",
// "f":"6968","g":"ad3283ca38a64955083e8bf7746f6305","h":"1","t":1,"o":0,
var FileInfo = function(str)
var info;
try
info = JSON.parse(str.replace(/([^]+),?/, "$1"));
catch(e)
var isHit = false;
var fullname = null;
return
get IsValid() return info && info.a && info.b; ,
get filename() return info.a; ,
get hash() return info.b; ,
get size() return info.c; ,
get dlSubFolder() return info.d; ,
get dlSuccess() return info.e; ,
get downloadSize() return info.f; ,
get downloadHash() return info.g; ,
get autoUncompress() return info.h; ,
get optional() return info.o; ,
get fileType() return info.t; ,
get IsHint() return isHit ;,
markHit : function () isHit = true; ,
get Fullname()
if(fullname == null)
if(okFiles)
var reg = /.\\/([^\\.]+)\\.ddx/;
if(reg.test(this.filename))
fullname = okFiles[this.filename.replace(reg, "$1")];
if(fullname==null)
fullname = "-";
return fullname;
,
get desc()
return `$this.filename : $this.Fullname : $this.optional ? "optional" : "required"`;
;
var dict = ;
var okFiles = ;
var md5 = str => require('crypto').createHash('md5').update(str).digest('hex'); // MD5相关算法
var tmpDirs = [];
tmpDirs.push(".");
// 遍历文件夹,并计算MD5
var myIter = function(cur)
// console.log(cur);
var full = path.join(baseDir, cur);
fs.readdirSync(full).forEach(f =>
if(!f.startsWith("."))
var tmp = path.join(cur, f);
if(fs.statSync(path.join(baseDir, tmp)).isDirectory())
tmpDirs.push(tmp);
else // 计算MD5
if(!f.endsWith(".meta") )
var fn = `SuI9_hero_project_2014/$tmp.toLowerCase().replace(/\\\\/gi, "/").replace(/([^\\.]+)\\..+$/, "$1").assets`;
var m = md5(fn); // MD5的用法
okFiles[m] = tmp;
);
var readDirs = new Promise((resolve, reject) => // 读取本地文件,并形成字典
while(tmpDirs.length > 0) // 处理所有的文件
myIter(tmpDirs.shift()); // queue的用法
resolve();
);
readDirs.then(r=>
exec('adb pull /sdcard/Android/data/com.ucool.heroesarena/fileList4.json') // 拉取fileList4.json
).then(r => // 解析文件
return new Promise((resolve, reject) =>
if(!fs.existsSync(jsonName))
return reject();
var lr = require('readline').createInterface(
input: fs.createReadStream(jsonName)
);
lr.on('line', line =>
var info = new FileInfo(line);
if(info.IsValid)
dict[info.filename] = info;
).on('close', v =>
resolve();
);
);
).then(r => // 列出手机上相应目录下的文件名
return exec('adb shell "cd /sdcard/Android/data/com.ucool.heroesarena/patch6 && find . -type f \\\\( -name \\"*.ddx\\" -o -name \\"*.bnk\\" \\\\) -print0 | xargs -0 ls -al"');
).then(r => // 尝试对比,是否有文件缺失
return new Promise((resolve, reject) =>
//-rw-rw---- 1 u0_a260 sdcard_rw 85794 2018-03-21 14:45 ./c/cf9da209844daa8db78dd4140e000c34.ddx
var reg = /(?:\\S+\\s+)4(\\d+)\\s+(?:(?:\\S+\\s+)2)\\.\\/([^\\r\\n]+)/g;
// 全局文本搜索 https://stackoverflow.com/questions/1222045/how-to-loop-all-the-elements-that-match-the-regex
var m;
while((m = reg.exec(r)) !== null)
var f = dict[m[2]];
if(f)
if(m[2].startsWith("Audio"))
// console.log(m[2]);
f.markHit();
else
console.log(`$f is not exists in fileList4.json!`);
resolve();
);
).then(r => // 打印结果
Object.keys(dict).forEach(key =>
var f = dict[key];
if(!f.IsHint)
console.log(`NOT FOUND:: $f.desc`);
);
console.log("============== Run Finished!!==================");
// delJson();
) .catch(r =>
console.log(`Error: $r`);
// delJson();
);
一个词典:
var fs = require('fs');
var lr = require('readline').createInterface(
input: fs.createReadStream('words1M.csv')
);
var pageSize = 30;
var pattern = process.argv[2].replace(/(\\*)/g, "\\.$1").replace(/(\\?)/g, "\\.$1");
var page = parseInt(process.argv[3]) || 0;
var skip = page * pageSize;
re = new RegExp(`^$pattern$`); // /^.*acro.*$/i;
var count = 0, lc = 0;
lr.on('line', line =>
lc++;
if(re.test(line))
count++;
if(count > skip && (count - skip) <= pageSize)
console.log(`$("" + count).padEnd(5)$line.padEnd(20)$("" + (lc/10000).toFixed(4)).padStart(8)`);
).on('close', v =>
console.log('---------------------------------------');
console.log(`$pattern page: $page/$parseInt(count/pageSize) total: $count`);
);
一个单词查询工具
var fs = require('fs');
const readline = require('readline');
var lr = readline.createInterface(
input: fs.createReadStream('words1M.csv')
);
var dict =
var init = function(total)
var acc = total / 10, acc_ = 0;
process.stdout.write('Loading');
return new Promise((resolve, reject) =>
var lc = 0;
lr.on('line', line =>
lc++;
if (lc > total)
return;
var w = line;
var next = dict;
for (var j = 0; j < w.length; j++)
var c = w.charAt(j);
if (next[c] == null)
next[c] = ;
next = next[c];
if (next)
if (next['@'] == null)
next['@'] = lc;
else
// console.warn("has number!");
if(++acc_ > acc)
acc_ = 0;
process.stdout.write('.');
).on('close', v =>
resolve();
);
);
;
var search = w =>
var next = dict;
for (var i = 0; i < w.length; i++)
var c = w.charAt(i);
if (next[c] != null)
next = next[c];
else
next = null;
break;
return next && next['@'] || -1;
const rl = readline.createInterface(
input: process.stdin,
output: process.stdout
);
var query = function()
return new Promise((resolve, reject) =>
rl.question('> ', w =>
if(w.length == 0)
resolve();
return;
var ss = w.split(',');
var rt = [];
for(var s of ss)
s = s.trim().toLowerCase();
var idx = search(s);
if(idx > 0)
rt.push([s, idx]);
rt.sort((lhs, rhs) => lhs[1] - rhs[1]);
var l1 = "", l2 = "", ls = "";
for(var s of rt)
var wl = s[0].length;
var ll = 15;
while(ll<=wl)
ll += 15;
l1 += s[0].padEnd(ll);
ls += "".padEnd(ll, '-');
l2 += s[1].toString().padEnd(ll);
resolve(`$l2\\r\\n$ls\\r\\n$l1\\r\\n\\r\\n`);
);
);
;
(async function()
await init(800000);
while(true)
var result = await query();
if(result)
console.log(`$result`);
)();
1. 介绍Java面向对象,很好的书籍:
《The principles of Object-Oriented javascript》 by Nicholas C. Zakas
2. 介绍Node.js很好的书籍(目前感觉Stream和pipe方面的介绍非常ok):
《Node.js Design Patterns》by Mario Casciaro
以上是关于Node.js脚本集锦的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Node.js 设置为始终在服务器(如 Apache)上运行 [重复]