在将日志文本解析成结构化数据时时,常会遇到记录由数量不定的多行组成的情况。这种变换存在一定的复杂性,实现复杂度较高。集算器支持正则表达式、字串拆分、隔行取数、横向拼接等灵活的结构化计算函数,适合处理此类文本。下面通过例子来看一下具体作法。
日志文件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中的循环,或是从缓冲区直接返回数据,整个过程自动完成。
相关推荐
结构化文本(Structured Text, ST)是IEC 61131-3标准定义的五种编程语言之一,适用于高级逻辑和数学运算,尤其适合编写复杂的控制程序。本资料合集主要关注的就是如何使用ST语言来对三菱PLC进行编程。 《三菱Q-L...
结构化文本(ST)编程(GX Developer用),三菱官方教程
总结来说,百度富文本解析工具是百度小程序开发中的一个重要组件,它提供了丰富的文本格式化能力,帮助开发者轻松地处理和展示用户生成的富文本内容。理解和熟练使用这个工具,将极大地提升百度小程序的交互性和内容...
《日志服务数据加工:非结构化数据解析实践》 日志服务是针对日志分析领域的一款强大工具,它的核心功能在于将各种非结构化的日志数据转化为结构化数据,以便进行实时处理、数据仓库计算以及数据分析。日志服务具备...
特别是非结构化文本数据,它们包含着大量的有价值信息,但同时也因为复杂多变,不易于管理和分析。本文将深入探讨银行非结构化文本数据背后的价值,并提供相应的利用策略。 首先,我们必须明确什么是非结构化文本...
结构文本是一种高级语言,如果你知道如{可使用高级语言来编程,像:Basic、 PAC SAL或C,那么你会很轻松的掌握StructuredText CST)编程:如果不知道,你会看到ST有着简单、标准的结构,保证程序高效、快速运行并...
数据结构与文本格式化是计算机科学中的两个重要概念,它们在编程、软件开发以及数据分析等领域中扮演着核心角色。理解并掌握这些知识点对于任何IT专业人员来说都是至关重要的。 首先,我们来探讨“数据结构”。数据...
"PLC结构化文本编程一本通" PLC结构化文本编程是一种重要的编程方法,广泛应用于工业自动化领域。本书《PLC结构化文本编程一本通》是一本全面介绍PLC结构化文本编程的实用指南,旨在帮助读者快速掌握PLC编程的核心...
Spell方法的核心是利用最长公共子序列算法来解析非结构化的系统日志。与传统的离线批量处理方式相比,Spell在日志条目到达时立即进行处理,大幅提升了处理速度,尤其适合需要实时反馈的场景。这种在线流式解析技术,...
文本解析是一种从非结构化或半结构化的文本数据中提取有意义信息的过程。在“文本格式表数据”中,数据通常以行和列的形式组织,类似于数据库中的表格。每一行代表一个记录,每一列则对应一个字段。这些数据可以是...
在现代银行业,非结构化文本数据正逐渐成为挖掘潜在价值的重要资源。这些数据包括但不限于客户的电子邮件、社交媒体评论、贷款申请的自由格式文本、内部报告、合同文档等,它们蕴含着丰富的信息,等待着被深入理解和...
在Android平台上,富文本解析是实现复杂文本展示和编辑的关键技术。富文本解析器能够将HTML和Markdown这两种标记语言转化为可读性强、样式丰富的文本,为用户提供了更佳的视觉体验。本文将深入探讨Android环境下如何...
# 这里写正则表达式或其他逻辑来解析日志行 ... with open('E:/nextcloud.log', 'r') as file: log_data = [] for line in file: parsed_line = parse_log(line) log_data.append(parsed_line) df = pd....
这个"JavaScript_使用GPT3从非结构化文本中推断知识图.zip"压缩包显然涉及到如何利用JavaScript与GPT-3(Generative Pre-trained Transformer 3)模型进行交互,以从非结构化的文本中抽取并构建知识图谱。...
Harnessing Text Structure Strategy for Reading Expository and Medical Texts among EFL College Students
2. **分割日志行**:根据日志格式,使用`String`的`split()`方法或正则表达式分割日志行,提取所需字段。例如,如果日志以空格分隔,可以使用`split("\\s+")`。 3. **数据转换**:将分割后的字符串转换为适当的类型...
ANTLR(ANother Tool for Language Recognition)是一个开源的解析器生成器,主要被...通过学习和掌握ANTLR,开发者能够高效地实现对结构化文本或二进制文件的读取、处理、执行和翻译,从而提升软件开发的效率和质量。
文本图谱化,文本解析成图谱表示,包含ner和textrank等技术,应用ltp模型进行ner,将文本转化为echarts.js支持的图谱展示;包含ner和textrank等技术,应用ltp模型进行ner,将文本转化为echarts.js支持的图谱展示;
3. **数据结构**:常见的数据结构如链表、栈、队列、树等在文本格式化中可能发挥作用。例如,使用链表来存储行或单词,栈来实现嵌套的括号匹配,队列可以用于逐行读取和处理文本。 4. **文件操作**:`fopen()`打开...