2012-08-14 65 views
1

我有一个半结构化的文本文件,我想从中提取值并保存起来以备后用。 该文件有一些模拟环境的配置数据env。由不同的子系统组成,对于其中一个子系统,我希望找到它们的数量,以及它们的具体类型。 这是文件是如何构成的使用Tcl解析结构化文件并选择一些值?

<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脚本

感谢您的帮助

回答

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或将对的列表转换为数组,以便查找。

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> 
+0

如果我们有什么,多个IP地址线。如何grep所有IP地址。 Subsystem_Type:PLC_BERGHOF: IP_Address:“11.70.9.13”: Port_Numbers:3500:3500: Alive_Message_Period:10:如何grep“11.70.9.13”和10.70.9.11。 – rcubefather 2014-09-03 11:26:42

+0

然后,如果我们替换它,它会打印任何内容,而不是'设置数据([lindex $ fields 0])$ values''您希望'lappend data([lindex $ fields 0])$ values' – 2014-09-03 12:28:04

+0

。如何解决这个问题。请帮忙。 – rcubefather 2014-09-04 15:19:48