使用Tcl解析结构化文件并选择一些值?

时间:2012-08-14 11:50:59

标签: parsing tcl

我有一个半结构化的文本文件,我想从中提取值并保存它们供以后使用。 该文件包含一些模拟环境的配置数据,即env。由不同的子系统组成,对于其中一个子系统,我想找到它们的数量,以及它们的具体类型。 这就是文件结构的方式

<Begin_Subsystem_Configuration>
Subsystem_Name:"PLC1_ARR":
Subsystem_Identifier:0x01B1B000:
Subsystem_Type:PLC_BERGHOF:
IP_Address:"10.70.9.11":
Port_Numbers:3500:3500:
Alive_Message_Period:10:
Max_Communication_Latency:5:
Switch_Over_Timeout:15:
Member_Count:6:
Subsystem_Member_1:77:77:       # PS SR1
Subsystem_Member_2:106:106:     # SZ PTHA
Subsystem_Member_3:110:110:     # SZ PTH1
Subsystem_Member_4:310:310:     # SZ YL1
Subsystem_Member_5:311:311:     # SZ DOOR1
Subsystem_Member_6:312:312:     # SZ FIRE1
<End_Subsystem_Configuration>

现在我想知道,模式PLC_BERGHOF在文件中出现的频率,我实际上已经可以做到了,但现在如果找到它我想保存在某种类型的关联中。数组前一行的键值对,以及发现模式的行后面的3行。

稍后在我的脚本中,我希望能够访问这样的值: 设置plc1_IP_Address数组['plc1_IP_Address'],  访问的确切sysntax并不重要,代码只需要进入Tcl脚本

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

如果您使用的是Tcl 8.5,那么我建议您逐行读取文件,构建一组dict个对象,将每个子系统保存为名称:项目对的集合。然后,您可以创建此类词典的列表,以表示整个文件或对您有意义的任何内容。然后是:

foreach config $list_of_dicts {
    if {[dict get $config Subsystem_Type] eq "PLC_BERGHOF"} {
        puts "[dict get $config IP_Address]\n[dict get $config Port_Numbers]"
    }
}

虽然根据您的说明声明:grep -A 3 PLC_BERGHOF就足够了。

如果不使用8.5,那么您没有dict,但可以以相同的方式管理名称项对的列表。您最后使用lsearch或将对列表转换为数组只是为了查找内容。

答案 1 :(得分:0)

set fh [open "file.data" r]
array set data []
while {[gets $fh line] != -1} {
    switch -exact -- $line {
        "<Begin_Subsystem_Configuration>" -
        "<End_Subsystem_Configuration>"   {continue}
        default {
            set fields [split $line ":"]
            set values [list]
            foreach value [lrange $fields 1 end-1] {
                if {[string match {"*"} $value]} {
                    lappend values [string range $value 1 end-1]
                } else {
                    lappend values $value 
                }
            }
            set data([lindex $fields 0]) $values
        }
    }
}
close $fh

然后你可以使用

if {$data(Subsystem_Type eq "PLC_BERGHOF"} {
    puts "IP address is: $data(IP_Address)"
}

我认为您的文件实际格式如下,并且您无法正确格式化问题:

<Begin_Subsystem_Configuration>
Subsystem_Name:"PLC1_ARR":
...
<End_Subsystem_Configuration>