在将日志文本解析成结构化数据时时,常会遇到记录由数量不定的多行组成的情况。这种变换存在一定的复杂性,实现复杂度较高。集算器支持正则表达式、字串拆分、隔行取数、横向拼接等灵活的结构化计算函数,适合处理此类文本。下面通过例子来看一下具体作法。
日志文件reportXXX.log存储着若干记录,每条记录由多行构成,包括14个数据项(字段)。记录以字符串“Object Type”开头。我们的目标是把该日志整理为结构化数据,并将结果写入文本文件。部分源数据如下:
集算器代码:
A1=file("e:\\reportXXX.log").read()
这句代码用来将日志文件全部读入内存,结算结果如下:
A2=A1.array("Object Type: ").to(2,)
这句代码可以分解为两部分。第一部分:将A1按照”Object Type”分割为多个字符串,代码为A1.array("Object Type: "),计算结果如下:
第一条数据无用,之后的每条数据都是一条有效记录,to(2,)表示取出第二条直至最后一条数据。A2的计算结果如下:
A3= regex(正则表达式;字段名列表),这句代码对A3中的每个成员应用同样的正则表达式,并取出14个字段,字段名以逗号分割。下面列出计算结果中的前几个字段:
A4=file("e:\\result.txt").export@t(A3)
上面的代码用来将计算结果写入文件,默认的分割符是tab,选项@t表示将字段名做为文件的第一行。打开result.txt,可以看到下面的数据:
上面代码的正则表达式有些复杂难懂,如果想更直观地解决问题,也可以使用集算器的内置函数。比如:ObjectType字段其实是每条记录的第一行,因此可以先将每条记录按照换行符分,再取第一行。再比如left\top\right\bottom其实是将每条记录的第2行按照空格分割,分别取出第3、5、7、9项。
下面用集算器内置函数来解决本案例:
上述代码中,函数pjoin可将多个集合横向拼接起来,函数array可将字符串按指定分隔符分成多段,并形成一个集合,其中(~.array("\r\n")表示对每条记录按照回车换行拆分。
在前面的案例中,我们假设文件比较小,可以全部读入内存计算,但有时日志文件太大,必须分批读取,分批解析,分批写入文件,开发难度因此会显著提高。由于记录的行数不定,一批数据中总会出现半条记录的情况,处理起来会更加复杂。
集算器支持文件游标,适合处理这类不定行的大日志,代码如下:
A1=file("\\reportXXX.log").cursor@s()
这句代码以游标的方式打开日志文件。函数cursor表示根据文件对象返回游标对象,默认分隔符是tab,默认列名是_1,_2…_n。选项@s表示忽略分割符并将文件内容读成单列字符串,列名是_1。值得注意的是,这句代码只是建立游标对象,并没有读入数据,实际的读入动作会在遇到语句for或函数fetch时触发。
A2: for A1,10000
A2是个循环语句,表示每次从A1读入一批数据(10000行)并送入循环体,直到日志末尾。可以看到,集算器使用直观的缩进来表示循环体,而不是括号或begin/end等标识符。B3-B7就是A2的循环体,其处理过程是:将当前批次的数据按照回车换行符还原成文本,再按照“Object Type:”重新拆分成记录,将最后一条不完整的部分存储在临时变量B1中,并删除第一条和最后一条无用的记录,对剩下的每条记录进行正则表达式解析,形成的二维表追加到文件result.txt中。下面看详细说明:
B2=B1+A2.(_1).string@d("\r\n")
这句代码将临时变量B1和当前批次的文本拼在一起。第一次循环时B1为空,以后每次循环时B1会存储上个批次的半条记录,B1和当前批次的文本拼在一起,就会使半条记录变完整。
函数string可以把集合成员按照指定的分割符拼成一个大字符串,选项@d表示不在成员的两边加引号。比如第一次循环时,A2的前几行为:
A2.(_1)表示A2的字段_1形成的集合,即:
A2.(_1).string@d("\r\n")表示将上述集合拼成一个大字符串,即:Object Type: Symbol Location: left: 195 top: 11 right: 123 bottom: 15 Line Color: RGB ( 1 0 0 ) Fill Color: RGB ( 251 255 0 ) Link:l11….
B3=B2.array("Object Type: ")
这句代码将B2中的大文本按照“Object Type”分割为多个字符串。B3在第一次循环时计算结果如下:
由于B3中的最后一个字符串往往只有记录的一部分,无法参与完整计算,应该将它存在临时变量中,下次循环时再把它和新批次的字符串拼在一起。B4中的代码可以将该字符串存入临时变量B1。
B4=B1="Object Type: "+B3.m(-1)+"\r\n"
函数m表示正向或逆向取集合中的成员,取第一个可以写作m(1),取前三个写作m([1,2,3]),倒数第一个写作m(-1)。也可以直接用B3(1)来正向取第一个成员。另外,前面字符串拆分时已经去掉了每条记录开头的“Object Type”,所以这里要恢复原样。从cursor按行读文件时会去掉回车换行,这里补一个“\r\n”。
B3的第一个成员是空行,最后一个成员是半条记录,这两行都无法参与计算,可以使用下面的代码删除这两个成员:
B5=B3.to(2,B3.len()-if(A1.fetch@0(1),1,0)))
这句代码用来取出B3中的有效数据。如果当前批次不是最后一批,则第一条是空记录,最后一条是半条记录,应当取出第二条直至倒数第二条。如果当前批次是最后一批,则第一条是空记录,最后一条是完整记录,应当取出第二条直至最后一条。
函数B3.to(m,n)表示取出B3中序号在m和n之间的记录。B3.len()表示B3的记录数,相当于当前批次最后一条记录的序号。A1.fetch(n)表示取出游标A1中的n条行,选项@0表示只查看数据,游标位置并不移动。函数if有三个参数,分别是布尔表达式、表达式为true时返回的结果、表达式为false返回的结果。当前批次不是最后一批时,A1.fetch@0(1)为有效记录,函数if返回1;当前批次是最后一批时,A1.fetch@0(1)为空,函数if返回0。
B6=B5.regex(正则表达式;字段名列表),这句代码对B5中的每个成员应用同样的正则表达式,并取出14个字段,字段名以逗号分割。下面列出计算结果中的前几个字段:
B7=file("e:\\result.txt").export@a(B6)
这句代码将B6追加到result.txt中,每次循环追加一批记录,直到日志结尾。打开大文件result.txt可以看到本案例的最终计算结果:
上述算法中在循环中进行正则表达式解析,但正则表达式的编译性能较差,尽量不要在循环中使用,这时可以使用两个集算器脚本配合函数pcursor来实现流式分拆和解析。
首先是主程序main.dfx,代码如下:
函数pcursor调用了一个子程序,用来返回单列记录形成的游标。A2格对A1中的每条记录进行正则表达式解析,返回结构化数据。注意:A2的计算结果是游标,而不是内存中的数据,执行函数export时,游标A2才会被分批读入内存并进行计算,而这个分批的动作是自动完成的。
子程序sub.dfx的作用是返回游标,写法和前面的案例类似,不同之处是:无需写文件,直接返回单列记录,如下:
B6中的result可以将B5转为单列序表,并以游标的形式返回给调用者(main.dfx中的函数pcursor)。
通过函数pcursor,主程序main.dfx可以将子程序sub.dfx当做普通游标来取数,而不用管数据的生成过程。Main.dfx需要数据的时候,pcursor函数会根据缓冲区剩余的数据来判断是否继续执行sub.dfx中的循环,或是从缓冲区直接返回数据,整个过程自动完成。
相关推荐
《MELSEC-QL编程手册(结构化文本篇)》是一份由三菱公司编写的编程手册,专门针对MELSEC-Q系列和MELSEC-L系列可编程控制器(PLC)的结构化文本(ST)编程语言进行说明。手册内容详尽,为用户提供了从基础概念到具体...
结构文本是一种高级语言,如果你知道如何使用高级语言来编程,像Basic、PACSAL或C,那么你会很轻松的掌握Structured Text(ST)编程;如果不知道,你会看到ST有着简单、标准的结构,保证程序高效、快速运行并简单...
《结构化编程手册(顺控指令篇)》是针对三菱MELSEC-F FX系列PLC的一本专业指南,旨在帮助用户从传统的梯形图编程过渡到更高级的结构化文本ST语言编程。这本书主要介绍了如何使用顺控指令来编写结构化程序,从而提高...
详解银行非结构化文本数据背后的价值-匠心独运 厚积薄发.pdf
"PLC结构化文本编程一本通" PLC结构化文本编程是一种重要的编程方法,广泛应用于工业自动化领域。本书《PLC结构化文本编程一本通》是一本全面介绍PLC结构化文本编程的实用指南,旨在帮助读者快速掌握PLC编程的核心...
Spell方法的核心是利用最长公共子序列算法来解析非结构化的系统日志。与传统的离线批量处理方式相比,Spell在日志条目到达时立即进行处理,大幅提升了处理速度,尤其适合需要实时反馈的场景。这种在线流式解析技术,...
文本解析是一种从非结构化或半结构化的文本数据中提取有意义信息的过程。在“文本格式表数据”中,数据通常以行和列的形式组织,类似于数据库中的表格。每一行代表一个记录,每一列则对应一个字段。这些数据可以是...
内容概要:本文详细介绍了基于三菱FX3U PLC的四仓位配方控制系统,重点讲解了如何利用ST结构化文本和梯形图两种编程方式实现工业级配方管理。主要内容包括配方存储采用结构体数组的方式,使配方参数管理更加高效;...
在现代银行业,非结构化文本数据正逐渐成为挖掘潜在价值的重要资源。这些数据包括但不限于客户的电子邮件、社交媒体评论、贷款申请的自由格式文本、内部报告、合同文档等,它们蕴含着丰富的信息,等待着被深入理解和...
6. **定时任务调度**: 要实现日志解析和存储的自动化,通常会使用定时任务工具,如Linux系统的cron或Windows的任务计划程序。`modsecurity_log_mysql.py`脚本将被配置为定时运行,确保日志数据定期更新到数据库中。 ...
【医疗领域文本结构化】是信息技术在医疗健康领域的一个重要应用,主要目的是将非结构化的医疗文本转换成结构化的数据,以便于机器理解和处理。在医疗系统中,大量的医学报告、病例记录等文本数据蕴含着丰富的医疗...
### 基于改进HMM的半结构化文本信息抽取算法研究 #### 一、引言 随着互联网技术的快速发展,人类面临着前所未有的信息洪流。在这个背景下,如何有效地从大量的半结构化文本中提取有价值的信息成为了一个重要的研究...
非结构化文本没有固定的模式或格式,信息分布不均匀,可能包含多种形式的语言表达、拼写错误、语法变异、情感色彩等。这使得机器难以直接理解和处理。而结构化数据则具有明确的模式,例如数据库中的表格数据,每列都...
这个"JavaScript_使用GPT3从非结构化文本中推断知识图.zip"压缩包显然涉及到如何利用JavaScript与GPT-3(Generative Pre-trained Transformer 3)模型进行交互,以从非结构化的文本中抽取并构建知识图谱。...
在SQL Server中,数据库日志是数据库管理系统的重要组成部分,它记录了所有对数据库进行的事务操作,包括数据的插入、更新、删除以及数据库结构的修改等。这些日志信息对于数据库的故障恢复、审计追踪以及性能优化都...
Harnessing Text Structure Strategy for Reading Expository and Medical Texts among EFL College Students
`wal2json` 的工作原理是解析 PostgreSQL 的物理日志流,提取出每个记录的关键信息,如事务ID、命令类型、受影响的表和行等,并将这些信息构造成 JSON 对象。JSON 格式使得数据可读性更强,同时也更容易被其他系统和...
文章重点介绍了CGM文件二进制数编码的解析浏览及转换方法,文件的解析采用线性顺序与命令参数匹配结合的方式进行,既考虑了文档的完整性又不会明显降低解析效率。文件浏览充分利用Carnac.NET平台,结合当前油田系统...
富文本解析是指将包含各种格式如字体、颜色、链接、图片等的HTML字符串,转换成可被特定平台(这里指百度小程序)理解和渲染的结构化数据。bdParse实现了这一功能,使得开发者可以轻松地在百度小程序中展示复杂格式...