如何在TCL中操作文件中的每一行

如何在TCL中操作文件中的每一行,tcl,Tcl,我正在尝试使用tcl脚本将一些数据从iperf写入一个文件。该文件有100多行。现在我需要解析前10行,忽略它并考虑下一行10行并打印它,再次我需要忽略下一组10行,然后打印下一行10行,并一直持续到文件结束为止。我该怎么做 exec c:\\iperf_new\\iperf -c $REF_WLAN_IPAddr -f m -w 2M -i 1 -t $run_time > xx.txt set fp [open "xx.txt" r ] set file_data [read

我正在尝试使用tcl脚本将一些数据从iperf写入一个文件。该文件有100多行。现在我需要解析前10行,忽略它并考虑下一行10行并打印它,再次我需要忽略下一组10行,然后打印下一行10行,并一直持续到文件结束为止。我该怎么做

exec c:\\iperf_new\\iperf -c $REF_WLAN_IPAddr -f m -w 2M -i 1 -t $run_time  > xx.txt  

set fp [open "xx.txt" r ]
set file_data [read $fp]
set data [split $file_data "\n"]

foreach line $data {
    if {[regexp {(MBytes) +([0-9\.]*)} $line match pre tput]==1 } {
        puts "Throughput: $tput Mbps"
    }

正如您的示例所示,您已经了解了如何将一个(slurped)文件拆分为多行并逐个处理它们

现在实现“跳过十行、处理十行、再跳过十行”有什么问题?它只是使用一个变量来计算到目前为止看到的行数,并根据其值选择一个代码分支。对于Tcl,这种方法没有什么特别之处:有一些命令可用于计数、有条件地选择代码分支和控制循环

如果基于行计数器的当前值的分支看起来太蹩脚,那么可以围绕该计数器变量实现一个分支。但对于这个简单的例子,它看起来像是过度工程化

另一种方法是使用从
split
返回的列表中选择必要的行序列。这种方法可能会使用一个很好的属性
lrange
,它可以被告知返回一个子列表“从这个索引到列表的末尾”,因此解决方案实际上可以归结为:

set lines [split [read $fd] \n]
parse_header [lrange $lines 0 9]
puts [join [lrange $lines 10 19] \n]
parse_something_else [lrange 20 29]
puts [join [lrange $lines 30 end] \n]

对于小文件,此解决方案看起来非常紧凑和干净。

如果我理解正确,您希望打印第11-20、31-40、51-60行,。。。以下内容将满足您的要求:

package require Tclx

set counter 0

for_file line xxx.txt {
    if {$counter % 20 >= 10} { puts $line }
    incr counter
}

Tclx包提供了一种从文件中读取行的简单方法:for_file命令

+1,而不是可见的正则表达式。jwz会感到骄傲的!