Tcl:如何打印一套

Tcl:如何打印一套,tcl,Tcl,我要解析的文件如下 Name : John Pin : 5400 Age : 40 Place: Korea Amount : 4000 Name : Peter Pin : 6700 Age : 10 Place : Japan Amount : 3600 我的tcl代码是 set start "Name" set pn "Pin" set ag "Age" set ag_cutoff 15 set amnt "Amount" foreach line [split $content "\n

我要解析的文件如下

Name : John
Pin : 5400
Age : 40
Place: Korea
Amount : 4000
Name : Peter
Pin : 6700
Age : 10
Place : Japan
Amount : 3600
我的tcl代码是

set start "Name"
set pn "Pin"
set ag "Age"
set ag_cutoff 15
set amnt "Amount"
foreach line [split $content "\n"] {
   if {[regexp $start $line]} {
      set count 1
      set l1 $line
   }
   if {[regexp $pn $line] && $count ==1} {
       set pin_val [lindex $line 2]
       set l2 $line
   }
   if {[regexp $ag $line] && $count ==1} {
      set ag [lindex $line 2]
      if { $ag > $ag_cutoff} {
          set rep_taken 1
          set l3 $line
      }
      if {[regexp $amnt $line] && $count ==1 && $rep_taken == 1} {
          set age_val [lindex $line 2]
          puts $op1 "$ag $age_val "
          puts $op2 "$l1\n$l2\n$l3\n"
      }
此代码适用于绘图

但是,我还想o/p一个带有完整集合的文件,其中$ag>$ag\u。 现在使用puts$op3“$l1\n$l2\n$l3\n”-->可以打印到文件中。但如何打印未评估的行位置。有没有更好的方法来实现这一点

Name : John Pin : 5400 Age : 40 Place : Korea Amount : 4000 姓名:约翰 Pin:5400 年龄:40 地点:韩国 金额:4000
让解析循环只创建一个字典会简单得多(这将替换上面的代码):

如果第一行不是以“Name”开头,或者冒号和单词之间缺少空格,或者一个值由多个单词组成,则会发生爆炸。所有这些都很容易修复

例如,这里是一个扩展版本,用于解决最后两个问题(如果出现):

set data {}
set count 0
foreach line [split $content \n] {
    set keyword [string trimright [lindex $line 0] :]
    set value [string trimleft [lrange $line 1 end] {: }]
    if {$keyword eq "Name"} {
        incr count
    }
    dict set data $count $keyword $value
}
存储所有记录后,可以使用字典迭代输出选定的记录:

set ag_cutoff 15
dict for {count record} $data {
    if {[dict get $record Age] > $ag_cutoff} {
        dict for {k v} $record {
            puts "$k : $v"
        }
    }
}
这也意味着您可以继续向记录中添加字段,并且代码仍然可以正常工作,而不会发生更改

注意事项

如果
content
中的数据在开头或结尾或某些行之间有空行,则这些方法将不起作用。防止开头或结尾出现空行或空行的一种简单方法是替换

foreach line [split $content \n] {

如果数据中可能出现空行/空行,可以使用此选项跳过它们:

foreach line [split $content \n] {
    if {[string is space $line]} continue
如果100%确定所有数据都是正确的列表形式,则可以直接在其上使用诸如
lindex
之类的列表命令(但有点代码难闻)。如果不太确定,或者希望更准确,则应在处理每一行之前将其转换为列表:

foreach line [split $content \n] {
    set line [split $line]

文档:,,,,,

因此,
名称:
行标记每条记录的开始?是,它以金额结束。可以打印行,但不能通过放置$op2“$l1\n$l2\n$l3\n”完成设置。但仍然无法打印完整的套件,包括Place:Korea您需要在Place和:之间留一个空白,才能输出韩国。@PeterLewerin不明白您的意思。我的疑问是如何打印未在一组中计算的行。我是否应该为Place或任何其他行执行伪regexp。请注意在字符串
$line
上使用
lindex
。您应该在loop@glennjackman:由于原始代码假定文件数据是“列表安全的”,我冒昧地让我的代码假定相同的内容。
foreach line [split $content \n] {
    if {[string is space $line]} continue
foreach line [split $content \n] {
    set line [split $line]