在之前交接的工作中,页面本地调试有问题,因为它的数据是后台实时上报的,每次都会报bug,会给几兆肉眼分析日志,手动解读页面逻辑,太难了。。。后面把mock的逻辑加到页面上,但是遇到了一个问题,就是将log中的数据配置到mock接口=>于是有了写个脚本从log文件中提取json数据的想法。如何识别json字符串,使用正则模式匹配json,json的数据格式不一致,多层嵌套{}。=>放弃替换方案:来自StackOverflow>>原理:通过“{}”对字符串进行识别和拦截,使用JSON.parse尝试对拦截的字符串进行转换,成功则返回,失败(抛出异常)然后catch异常并继续缩小字符串内容的范围。这段的原理逻辑不能识别所有的json,最先出现的json先匹配。我改成从后往前识别json,主要是日志结合需求关注json函数extractJSON(str){varfirstOpen,firstClose=str.length-1,candidate;firstClose=str.lastIndexOf('}');do{//调试器firstOpen=str.indexOf('{');//console.log('firstOpen:'+firstOpen,'firstClose:'+firstClose);如果(firstClose<=firstOpen){返回空值;}do{candidate=str.substring(firstOpen,firstClose+1);//console.log('候选人:'+候选人);尝试{varres=JSON.parse(candidate);返回[res,firstOpen,firstClose+1];}catch(e){//console.log('...失败');}firstOpen=str.indexOf('{',firstOpen+1);}while(firstClose>firstOpen&&firstOpen!==-1);firstClose=str.lastIndexOf('}',firstClose-1);}while(firstClose!=-1);返回空值;这样就可以解决如何从一段文本中提取json内容了。接下来就是如何合理提取json了。日志文件内容的特点是每一行的输出信息,基本上每一行都可以提取一个关键的json数据,所以可以使用nodejs的stream实现逐行读取同时提取json时间参考>>注:我只是喜欢用stream来处理文件,方便阅读。对于比较大的文件(我遇到的log不超过1g),可以根据参考链接中的event-stream来处理这部分。内容不再赘述,直接贴代码。constfs=require('fs');constreadline=require('readline');conststream=require('stream');constinstream=fs.createReadStream('test.log.txt');constoutstream=newstream();constrl=readline.createInterface(instream,outstream);functionextractJSON(str){varfirstOpen,firstClose=str.length-1,candidate;firstClose=str.lastIndexOf('}');do{//调试器firstOpen=str.indexOf('{');//console.log('firstOpen:'+firstOpen,'firstClose:'+firstClose);如果(firstClose<=firstOpen){返回空值;}do{candidate=str.substring(firstOpen,firstClose+1);//console.log('候选人:'+候选人);尝试{varres=JSON.parse(candidate);//console.log('...found');返回[res,firstOpen,firstClose+1];}catch(e){//console.log('...失败');}firstOpen=str.indexOf('{',f首先打开+1);}while(firstClose>firstOpen&&firstOpen!==-1);firstClose=str.lastIndexOf('}',firstClose-1);}while(firstClose!=-1);returnnull;}//记录行数letlineCount=0;//收集json数据constresults=[];rl.on("line",lineStr=>{lineCount++;constextractRes=extractJSON(lineStr);if(extractRes){results.push({line:lineCount,content:extractRes[0]})}});rl.on('close',()=>{//过滤采集到的json数据,提取目标jsonconstfileContents=results.filter(res=>res.content.msg_content);//一般有很多结果,直接写到输出文件中fs.writeFileSync('res.txt',fileContents.map(obj=>{return'line:'+obj.line+'\n'+JSON.stringify(obj.content);}).join('\n\n'));});这样可以方便在写完脚本后过滤日志文件,提取必要的信息进行分析,也可以作为mock,发现从代码中复制出来的代码粘贴到sf编辑器中,\会加转义符,必须复制到sublime再复制回来才能正常--||
