Arrays TCL读入结构化文件并将内容输入数组

Arrays TCL读入结构化文件并将内容输入数组,arrays,tcl,Arrays,Tcl,我正在使用TCL读取以下格式的文件: 第1、1.2和3.4条 第2、5.6和7.8条 第三条等 代码需要假定在读取文件之前,密钥的值是未知的 我需要文件以数组结束,以便与其他现有代码保持同步 我试过了 array set FileA set libDir "/tmp/" set Datafile [open $libDir\Data.csv RDONLY] set DataFileB [split $Datafile "\n"] foreach line $DatafileB {

我正在使用TCL读取以下格式的文件:

第1、1.2和3.4条

第2、5.6和7.8条

第三条等

代码需要假定在读取文件之前,密钥的值是未知的

我需要文件以数组结束,以便与其他现有代码保持同步

我试过了

array set FileA
set libDir "/tmp/"

set Datafile [open $libDir\Data.csv RDONLY]

set DataFileB [split $Datafile "\n"]

foreach line $DatafileB {

    [lappend FileA [split $line ","]]

)

## also tried:

while {![eof $Datafile]} {
    set DatafileB [string trim [gets $Datafile]]
    puts -nonewline "'$DatafileB'"
    if {$DatafileB == {}} {continue}
    puts "EMFLimits contents are $DatafileB "
    set FileA [split $DatafileB ","]
    foreach {i j} $FileA {}
    set key $i
    set val $j
    set FileAurrents [split [gets [open $libDir\EFM_CurrentLimit.csv RDONLY]]]
    if {[info exists FileA($key)]} {
        lappend FileA($key) $val
    } else {
        set FileA($key) [list $val]
    }
    }
我一直得到一个空数组


我是TCL的新手,几周来一直被这个简单的谜题绊倒在其他工作中。

我不太明白你想做什么,但是如果你想用文件的内容填充数组,那么两次尝试都有一些错误

您的第一次尝试:

array set FileA    ;# This should have raised an error without the empty list
array set FileA {} ;# You can create a new array like this
set libDir "/tmp/"

set Datafile [open $libDir\Data.csv RDONLY]

set DataFileB [split $Datafile "\n"]  ;# open creates a channel for the file. If you do 
                                       # puts $Datafile, you will see something 
                                       # like file225721ca0b0 instead of the actual 
                                       # contents, so you won't get anything useful here

set fileContents [read $Datafile] ;# This gets all the contents of the file

close $Datafile                   ;# Closing a channel after use is a good practice

set DataFileB [split $fileContents "\n"] ;# And now we split

foreach line $DataFileB {             ;# Variable names are case sensitive. Be consistent
    [lappend FileA [split $line ","]] ;# You cannot use lappend on an array. In Tcl, there
                                       # is a difference between arrays and lists. 
                                       # lappend essentially stands for list append. 
                                       # This line should raise an error

    # You can use a bit of the code you used in your second attempt:
    foreach {i j} [split $line ","] {}
    set key $i
    set val $j
    if {[info exists FileA($key)]} {
        lappend FileA($key) $val
    } else {
        set FileA($key) [list $val]
    }
} ;# How did this become a parenthesis? It should be a brace

parray FileA   ;# You can use this to pretty print the contents of the array
至于你的第二次尝试

while {![eof $Datafile]} {
    set DatafileB [string trim [gets $Datafile]]
    puts -nonewline "'$DatafileB'"
    if {$DatafileB == {}} {continue}
    puts "EMFLimits contents are $DatafileB "
    set line [split $DatafileB ","]  ;# FileA is an array you created. This line should 
                                      # raise an error because you are trying to overwrite 
                                      # the array with a "standard value". Use a different 
                                      # name. I will use line
    foreach {i j} $line {}
    set key $i
    set val $j
    set FileAurrents [split [gets [open $libDir\EFM_CurrentLimit.csv RDONLY]]] ;# You are 
            # not using this variable, so I don't know what you intend to do, but his line 
            # will continuously create new channels of the same file. You need to close 
            # channels after using them using close
    if {[info exists FileA($key)]} {
        lappend FileA($key) $val
    } else {
        set FileA($key) [list $val]
    }
}

close $Datafile
parray FileA
也就是说,我可能会写一些更像这样的东西:

array set fileA {}
set libDir "tmp"
set dataFile [open [file join $libDir Data.csv] r]
set fileContents [read $dataFile]
close $dataFile

foreach line [split $fileContents "\n"] {
    lassign [split $line ","] key val
    lappend fileA($key) $val          ;# lappend creates the variable if it does not 
                                       # already exists so it is pretty convenient
}

parray fileA

您可能应该对另一个文件执行类似的操作,并获取另一个数组,然后比较这两个数组,或者对这两个文件执行任何操作。

在我看来,您似乎从未真正读取过该文件。你打开它,然后把东西分成几行。在这两条语句之间,添加set contents[read$Datafile],然后在split语句中使用$contents。然而,第二个版本看起来应该是有效的。。。我假设你的Data.csv里面有好东西!而且该文件位于/tmp中,但是我们在文件名中使用了反斜杠?有点吓人。可以使用文件join$libDir Data.csv生成文件名。我们确信公开赛成功了吗?很抱歉漫无边际。如果这是一个选项,那么更改文件格式使其成为有效的tcl列表/dict会让生活变得更轻松。string1{1.2 3.4}string2{5.6 7.8}等等。然后你可以直接读它并使用dict命令。这是一个有趣的foreach循环。你期望它做什么?我还认为您需要查看变量名。FileA将是数组还是临时变量?我将使用lassign而不是foreach-这正是该命令的设计目的;设置行[split$contents\n]将导致列表的最后一个元素为空,因为文件数据以换行结束。为此,我非常推荐read-nonewline$chanThanks,我查看了实际的文件,并且在数组赋值的末尾使用了{},我以前的一些尝试非常接近。但你的第三个选择是正确的!