在Tcl脚本中转​​换列表中的列

时间:2019-04-02 15:27:57

标签: tcl

我想使用Tcl脚本将文件的一列转换为列表。我有一个文件名“ input.dat”,其数据分为两列,如下所示:

7 0

9 9

0 2

2 1

3 4

我想将第一列转换为列表,然后按如下方式编写Tcl脚本:

set input [open "input.dat" r]
set data [read $input]
set values [list]
foreach line [split $data \n] {

  lappend values [lindex [split $line " "] 0]
}

puts "$values"
close $input

结果显示为:7 9 0 2 3 {} {}

现在,我的问题是这两个额外的“ {}”是什么,脚本中的错误是什么,因为它会产生两个额外的“ {}”,我该如何解决这个问题?

有人可以帮助我吗?

3 个答案:

答案 0 :(得分:0)

那些大括号表示空字符串。您最常使用的文件的末尾可能会有几个空行。

您可以通过在lappend将第一列添加到values列表之前检查一行来避免这种情况:

foreach line [split $data \n] {
  # if the line is not equal to blank, then lappend it
  if {$line ne ""} {
    lappend values [lindex [split $line " "] 0]
  }
}

您也可以在获取结果列表后删除那些空字符串,但这意味着您将有两个循环。如果您无法帮助,它仍然会很有用。

例如,使用lsearch获取所有非空白的值(在这种情况下可能是最简单的):

set values [lsearch -all -inline -not $values ""]

也可以使用lmap来达到相同的效果(IMO稍微复杂一些,但是在遇到更复杂的情况时可以提供更大的灵活性):

set values [lmap n $values {if {$n != ""} {set n}}]

答案 1 :(得分:0)

第一个{}由3 4之后的空白行引起。

第二个{}由表示文件结尾的空白行引起。

如果从文件中删除了最后一个空白行,那么将只有一个{}。

如果然后按以下方式对循环进行编码,则将没有{}。

foreach line [split $data \n] {
    if { $line eq "" } { break }
    lappend values [lindex [split $line " "] 0]
}

@jerry有更好的解决方案

答案 2 :(得分:0)

除非间歇性的空字符串具有某些对程序任务很重要的含义,否则您还可以使用从Tcl列表(带有空字符串元素)到修剪空字符串元素(在结尾处以及之间):

concat {*}[split $data "\n"]