原创 TCL脚本对文本文件中的数据提取操作

2024-4-4 16:56 2502 8 5 分类: 医疗电子 文集: TCL/TK
项目调试的时候会产生很多类似的文本文件,这些文本文件可以在离线的时候进行处理。比如,最近需要对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 [open "1.txt" r]
  • ##set chan [open $OpenFileName r]
  • set myfile1 [open "PK.txt" w]
  • set myfile2 [open "ER.txt" w]
  • while {[gets $chan line] >=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是使用了匹配到数字后,提取到行尾结束本次提取,这样才得到所需的完整数据。


    作者: coyoo, 来源:面包板社区

    链接: https://mbb.eet-china.com/blog/uid-me-1010859.html

    版权声明:本文为博主原创,未经本人允许,禁止转载!

    PARTNER CONTENT

    文章评论0条评论)

    登录后参与讨论
    我要评论
    0
    8
    关闭 站长推荐上一条 /3 下一条