使用Tcl从列表中提取信息

时间:2017-11-07 15:36:23

标签: tcl

我有多个日志文件,其中包含带有标题的值:

我想创建一个头文件,其中包含第1列中的每一行作为单独的列标题,并且每行包含min - max并以列格式显示。

Info in log files: 

Trace Header                        Min         Max       Mean

aaa                                  1           6         xx
bbb                                  2           7         xxx

我想要的是什么:

aaa            bbb

1-6            2-7 

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

试试这个(长列表应该在data变量中,从文件中读取或其他):

foreach line [split $data \n] {
    if {[scan $line {%s %d %d} header min max] eq 3} {
        set result($header) $min-$max
    }
}
% parray result
result(aaa) = 1-6
result(bbb) = 2-7

scan命令在每行上查找三个字段,一个文本字段和两个十进制整数字段。匹配行报告找到的三个字段,空行或仅包含文本报告的行。如果找到匹配项,则会将其添加到结果中。

<强> ETA:

要处理您在评论中提到的真实日志文件:

foreach line [split $data \n] {
    if {[scan $line {%59[ #()-./0-9:=>A-Za-z]%s %d %d} header stuff min max] eq 4} {
        set result([string trim $header]) $min-$max
    }
}

(请注意,重复的标题会在数组中压缩为一个。)

如果字段中有空格,则无法使用%s使用数据。相反,您可以使用

找出标头可能包含的数据类型
% set chars [string map {\n {}} [join [lsort -unique [split $data {}]] {}]]
 #()-./0123456789:=>ABCDEFGHILMNOPRSTUVWXY[]abcdefghijklmnopqrstuvwxyz

易于简化现场规范

[ #()-./0-9:=>A-Za-z]

如果你需要能够匹配括号,请将它们放入:

[][ #()-./0-9:=>A-Za-z]

要分割包含大写文本和空白的行,那么只有等号和可能更多的空格直到行尾,

package require textutil::split
::textutil::splitx $data {(?n)^[[:upper:] ]+=+\s*$}

文档: eq (operator)foreachifjoinlsortpackageparrayregexpSyntax of Tcl regular expressionsscansetsplitstringtextutil::split (package)

答案 1 :(得分:0)

代码段:

set foo  {
Info in log files:

Trace Header                        Min         Max       Mean

aaa                                  1           6         xx
bbb                                  2           7         xxx
}

set pattern {^(.*)\s+(\d+)\s+(\d+)\s+.*$}
set result [regexp -line -inline -all -- $pattern $foo]
array set bar {}
puts "Here's one view..."
foreach {all item min max} $result {
    puts "$item $min-$max"
    set bar([string trim $item]) $min-$max
}
puts ""
puts "Here's another one..."
puts [join [lsort [array names bar]] "\t"]
foreach item [lsort [array names bar]] {
  puts -nonewline "$bar($item)\t"
}

执行输出:

Here's one view...
aaa                                  1-6
bbb                                  2-7

Here's another one...
aaa bbb
2-7 1-6