我有一个半结构化的文本文件,我想从中提取值并保存它们供以后使用。 该文件包含一些模拟环境的配置数据,即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脚本
感谢您的帮助
答案 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>