解析Tcl中

时间:2017-10-18 16:48:36

标签: tcl

我试图解析一个看起来像这样的ascii文本文件。

KEY1 VAL1
  KEY2 VAL2
    KEY3 VAL3
      KEY4 VAL4
  KEY5 VAL5
    KEY6 VAL6
      KEY7 VAL7
KEY8 VAL8
  KEY9 VAL9

我想将此转换为KEYs 1,5,7的值的平面表。我有一个非常丑陋的强力算法循环文件并设置标志来读取值,但这并不是最有效的。

类似的东西:

set f [open $filename]
set data [split [read $f] "\n"]
foreach line $data {
  if {[string match KEY1* $line] ==1} {set key1match 1}
  if {($keymatch1==1) && ([string match KEY5* $line] ==1} {set key5match 1}
...

是否有更优雅的方式来生成此映射?

2 个答案:

答案 0 :(得分:0)

这是你想要的吗?

set keylist {}
set keyset {KEY1 KEY5 KEY7}
set flatDict {}
foreach line [split [string trim $input] \n] {
    if {[regexp {(\s*)(\w+)\s*(.*)} $line -> indent key val] && $key in $keyset} {
        set level [expr {[string length $indent] / 2}]
        set keylist [lrange $keylist 0 $level]
        lappend keylist $key
        dict set flatDict $keylist $val
    }
}

% set flatDict
KEY1 VAL1 {KEY1 KEY5} VAL5 {KEY1 KEY5 KEY7} VAL7

此代码保留一个键列表keylist,它根据缩进增长(通过lappend)和收缩(通过lrange)(并且完全取决于缩进是否正确)。仅考虑给定集合中的密钥keyset。对于添加到字典中的每个值,当前$keylist用作键(dict命令可以处理键层次结构,但是键必须是独立的而不是在列表中(例如{{ 1}})。

文档: && (operator)/ (operator)dictexprforeachifin (operator)lappendlrangeregexpsetsplitstringSyntax of Tcl regular expressions

事后补充:通过选择密钥,实际上不需要签订密钥列表。如果您只使用从根单线下降的键,则可以使用以下代码:

dict set myDict foo bar 123

请注意,在这两个示例中,我提供了可能包含空格的值。如果值始终是原子的,则可以使代码更加规则。

答案 1 :(得分:0)

这里有一些代码可以将数据解析为字典:

MouseDown

输出

set indent_width 2
set d [dict create]

set fh [open [lindex $argv 0] r]
while {[gets $fh line] != -1} {
    regexp {^(\s*)(\S+)\s*(.*)} $line -> indent key value
    if {$key eq ""} continue
    set level [expr {[string length $indent] / $indent_width}]

    dict set d $key level $level
    dict set d $key value $value
    dict set d $key children [list]
    dict set d $key parent ""
    dict set d last $level $key

    set prev_level [expr {$level - 1}]
    if {$prev_level >= 0} {
        set parent_key [dict get $d last $prev_level]
        dict update d $parent_key item {
            dict lappend item children $key
        }
        dict set d $key parent $parent_key
    }
}

dict unset d last

dict for {key value} $d {puts [list $key $value]}