项目调试的时候会产生很多类似的文本文件,这些文本文件可以在离线的时候进行处理。比如,最近需要对log文件里的某个或某几个参数进行提取,由于单个log文件中总共只包含了49组参数数据(每组包含5种不同的参数),一开始的时候觉得只有49组,手动提取到Excel中再进行分析处理,但是当log变多了以后,就会变得很繁琐,而且效率十分低下。 为了能够及时处理并从文本文件中提取感兴趣的数据,可以使用C++、Labview等编程语言编写简单的程序进行处理。我们在实际测试中,也是C程序员来帮助编写这种简便的”function“来帮助处理这些文本log文件。 用C语言处理这类文件,有几个弊端,比如大量的function功能块,C程序员需要花费精力进行管理,另外这些function的应用时,还是需要用户手动输入若干个匹配条件才能完成完整的处理。 此时,想到之前使用的TCL脚本开发的平台,包含了对文件的处理。虽然之前关注的是文本文件到二进制文件、或者二进制数据读取再写入文本文件的操作,这涉及数据的转换或者叫重新配置。当前log文件处理,只是对文件中的数据进行提取,或者说就是简单的对字符的提取处理,应该更简单,所以打算使用该平台额外添加一个功能来完成此功能。这里记录该功能开发的过程。 首先,我们来看log文件的格式,如下所示,为log文件中的前3组参数,每组5个一样的参数,这里列出了15行。 Crystal_ID: 0 PEAK: 103.00 L-FWHM: 96.83 R-FWHM: 108.13 ENERGY RESOLUTION (%): 10.97 Crystal_ID: 1 PEAK: 121.00 L-FWHM: 114.42 R-FWHM: 127.09 ENERGY RESOLUTION (%): 10.47 Crystal_ID: 2 PEAK: 121.00 L-FWHM: 114.98 R-FWHM: 127.92 ENERGY RESOLUTION (%): 10.69 log文件保存为任意名称的文本格式文件,我们感兴趣的是每组参数中的第二个和最后一个参数,即PEAK和ENERGY RESOLUTION这两个参数,实际我们需要提取的只是他们对应的数字而已。为了用TCL脚本处理,找来之前开发的平台,如图1所示。计划将按钮”创建MIF文件“功能修改成我们所需的功能;修改后的平台GUI如图2所示。 图1:现存的创建MIF文件的TCL/TK平台 图2:将图1中的按钮简单修改后的TCL/TK开发平台 下面着手修改按钮的具体功能,其基本功能应该包含打开log文本文件,提取匹配PEAK和ENERGY的行,从匹配到的行中提取所需的数据并存入到不同的文本文件中,这里使用PK.txt和ER.txt两个文件来分别进行存取。其完整代码如下所示, set chan ##set chan set myfile1 set myfile2 =0} { ;##依次整行读取字符 ##regexp {^(\w+)\s(\d+)} $line total ##lineStart num regexp {^\w+} $line lineStart ##通过正则表达式提取字符串头 regexp {\d+} $line num1 ##通过正则表达式提取字符串中数字段,无法提取小数点,并且小数点打断了完整数据提取 regexp {\d+.*$} $line num2 ##通过正则表达式提取字符中数字,由于数据位于行尾,通过起始数字加.*与字符串结尾符$完成了完整小数的提取。 ##.t insert end "\n$total" .t insert end "\n$lineStart" .t insert end "\n$num1" .t insert end "\n$num2" if {$lineStart=="PEAK" } { puts $myfile1 $num2 .t insert end "\n哈!Peak location 找到了!" } elseif {$lineStart=="ENERGY"} { puts $myfile2 $num2 .t insert end "\n哈!Energy Resolution 找到了!" } else { .t insert end "\n哦!这个不是我想要的!" } } close $chan close $myfile1 close $myfile2 点击“文本文件数据提取”按钮,其执行结果如图3所示 图3:点击按钮后其执行结果打印在文本显示窗口,同时还是创建两个文本文件来存储提取的数据 该功能的关键点主要有这几个: 1. 将log文件内容当成字符看待,后续操作均采用的是字符和字符串的操作; 2. 打开log文件后,首先逐行读取并判断; 3. 使用到正则表达式,regexp;使用regexp首先提取行头,判断是否是PEAK或ENERGY; 4. 判断遇到PEAK或ENERGY行后,再提取改行行尾数字;(注:实际操作是逐行读取并同时进行相关提取,后续通过if语句进行判决是否是需要的数据)。 5. 遇到需要的数据后,分别存储到对应创建的文件之中; 6. 完成最终操作,关闭所有打开的文件。 总结 在进行提取的时候其实遇到了一点问题,不同脚本开发软件或者C#语言都有正则表达式的操作。经过测试,似乎TCL的正则表达式操作限制更多,或者说我使用的TCL编译器版本低的问题,导致我使用的时候遇到一些问题。 这里首先感谢网络上分享的内容,比如这个: https://blog.csdn.net/tong66666666/article/details/134981436 我遇到的问题,其实在上述代码里的注释中有提到,即在提取数字的时候,遇到小数点就被打断,即正则提取的时候,没有识别小数或者小数点的方式。代码中使用两种方式来提取每个数字,比如图3中的ENERGY,分别提取为10和10.97,这当中,10.97是完整的能谱分辨率。提取的10是因为遇到小数点后,提取动作被打断后的结果。 我们的log由于将数字存放在了每个行的行尾,所以最终能够提取到完整的10.97是使用了匹配到数字后,提取到行尾结束本次提取,这样才得到所需的完整数据。