我的文件中包含以下格式的记录:
{TOKEN
{ NAME {name of this token} }
{ GROUPS {Group 1} }
{ VALUE value }
{ REPEATING {
{ MAX 3 }
{ TIME {nmin 30} }
} }
{ WINDOW */*/*/* }
{ ACTION {
{ EXEC {code to run here} }
} }
}
{TOKEN
{ NAME {name of next token} }
{ GROUPS {Group 1} }
{ VALUE value }
{ WINDOW 0/0:30-2:00,3:30-7:30/*/* }
{ HOST {localhost} }
{ ACTION {
{ email {
{ FROM cloverleaf@healthvision.com }
{ TO me@xxxx.org }
{ SUBJ {email subject test} }
{ MSG {this is the email body} }
} }
} }
并非所有记录都具有相同的关键字,但它们都是嵌套的键控列表,我需要将它们解析为.csv文件以便于查看。但是,当我读入文件时,它作为单个字符串而不是键控列表列表。在空格或换行符上拆分也无济于事,因为它们也位于键控列表中。我试图在} \ n和{T之间插入一个管道(|)并在管道上拆分,但我仍然最终得到了字符串。
我希望有人可以指出我正确的方向来解析这些s表达式文件。
提前感谢!
Ĵ
答案 0 :(得分:1)
以下是我了解您的问题的方法。
我建议把它变成一个字典,这是一个扁平的,而不是嵌套的结构。这应该使工作更容易。一旦你有一个平面列表,处理它变得更容易。这是我的解决方案:
# myscript.tcl
package require Tclx
proc makeKey {prefix key} {
return [string trim "$prefix $key"]
}
proc keyedlist2dict {klname {keyPrefix ""}} {
upvar 1 $klname kl
set d {}
foreach key [keylkeys kl] {
set value [keylget kl $key]
if {[catch {keylkeys value}]} {
# value is not a nested keyed list
lappend d [makeKey $keyPrefix $key] $value
} else {
# value is a nested keyed list
set d [concat $d [keyedlist2dict value $key]] ;# TCL 8.4
}
}
return $d
}
set contents [read [open data.txt]]
foreach item $contents {
# Each item starts with "TOKEN", which we need to remove otherwise
# the keyed list is invalid
set item [lrange $item 1 end]
# Convert a keyed list to a dict, then to a csv row. We can then
# display the row or to write it to a file.
set rec [keyedlist2dict item]
# Display it
foreach {key value} $rec { ;# TCL 8.4
puts "$key: $value"
}
puts ""
}
tclsh myscript.tcl
NAME: name of this token
GROUPS: Group 1
VALUE: value
REPEATING MAX: 3
REPEATING TIME: nmin 30
WINDOW: */*/*/*
ACTION EXEC: code to run here
NAME: name of next token
GROUPS: Group 1
VALUE: value
WINDOW: 0/0:30-2:00,3:30-7:30/*/*
HOST: localhost
email FROM: cloverleaf@healthvision.com
email TO: hardej@mmc.org
email SUBJ: email subject test
email MSG: this is the email body
keyedlist2dict
,在那里我拿出一个键入的列表并将其展平成为字典。
keyedlist2dict
我对标记为 TCL 8.4 的两行进行了更改。该脚本现在应该适用于TCL 8.4系统。
答案 1 :(得分:1)
这看起来像是一个TclX键控列表的列表,这是早期尝试做现代Tcl对词典的处理。键控列表很好地嵌套 - 这是一棵树,而不是一个表 - 所以映射到CSV将不是最有效的,但它们的语法是最简单的处理它们的方法是使用TclX代码。
预赛:
package require TclX
package require csv; # From Tcllib
列出我们感兴趣的列。注意名称的.
分隔位。
set columns {
TOKEN.NAME TOKEN.GROUPS TOKEN.VALUE TOKEN.REPEATING.MAX TOKEN.REPEATING.TIME
TOKEN.WINDOW TOKEN.HOST TOKEN.ACTION.EXEC TOKEN.ACTION.email.FROM
TOKEN.ACTION.email.TO TOKEN.ACTION.email.SUBJ TOKEN.ACTION.email.MSG
}
# Optionally, put a header row in:
puts [csv::join $columns]
将实际数据加载到Tcl:
set f [open "thefile.dta"]
set data [read $f]
close $f
迭代列表,提取信息,然后以CSV格式发送到stdout:
foreach item $data {
# Ugly hack to munge data into real TclX format
set item [list [list [lindex $item 0] [lrange $item 1 end]]]
set row {}
foreach label $columns {
if {![keylget item $label value]} {set value ""}
lappend row $value
}
puts [csv::join $row]
}
或类似的东西。
答案 2 :(得分:1)
我意识到这已经有几个月了,但我发现你正在尝试解析Cloverleaf配置文件(这就是我自己偶然发现的错误)。
对于其他任何尝试做类似事情的人来说,实际上有可用于处理Cloverleaf提供的库,但文档中没有提及它们。
查看$ HCIROOT / tcl / lib / cloverleaf。处理警报配置看起来像是在configIO.tlib中。 NetConfig的内容在nci.tlib和netData.tlib中。
答案 3 :(得分:0)
您可以将数据视为普通列表并逐行读取。 info complete
命令有助于此:
set fh [open your.file r]
while {[gets $fh line] != -1} {
append kl $line
if {[info complete $kl]} {
lappend lists $kl
set kl ""
}
}
close $fh
puts [llength $lists] ;# 2
puts [llength [lindex $lists 0]] ;# 1
puts [llength [lindex $lists 0 0]] ;# 7
puts $lists
{{TOKEN {NAME {此令牌的名称}} {GROUPS {Group 1}} {VALUE value} {REPEATING {{MAX 3} {TIME {nmin 30}}}} {WINDOW / / * / *} {ACTION {{EXEC {code to run here}}}}}} {{TOKEN {NAME {name of next token}} {GROUPS {Group 1}} {VALUE value} {WINDOW 0 / 0:30-2:00,3:30-7:30 / / } {HOST {localhost}} {行动{{email {{FROM cloverleaf@healthvision.com} {TO me @ xxxx .org} {SUBJ {email subject test}} {MSG {this is the email body}}}}}}}}