将 CSV 文件解析为 TCL

Parse a CSV file to TCL

我有一个文件如下:

a, b, c, d, e
S, 1.0, 100, F, fast
T, 2.0, 200, S, slow

第一行只有header(a,b,c,d,e),第2、3行是值(S,1.0,100,F,fast)对应header.

我想将下面的文件读入 tcl 并输出值(即:第 2 行,第 5 列 -> 快速)

我写了下面的脚本,但似乎没有用:

proc game {name infile outfile} {

    set csv [open $infile r]
    set csv_lines [read $csv]
    set out [open $outfile w]
    set info [split $csv "\n"]

    set infocount [llength $info]
    set line 1

    foreach line $info {
        set values [split $line ","]
        set firstline [lindex $values 0]
        set secondline [lindex $values 1]


    ### HOW DO I PUTS OUT ROW2 COL5 or ROW1 COL3 ###
       puts $outfile "$firstline"
    }

    close $infile
    close $outfile
}

想要输出文件如下:

a: S b: 1.0 c: 100 d: F e: fast
a: T b: 2.0 c: 200 d: S e: slow

a: T b: 2.0 c: 100 d: F e: slow
a: S b: 1.0 c: 200 d: F e: fast

使用 csv package from tcllib is the way to go for robustness, but on trivial data like this, split 即可。

#!/usr/bin/env tclsh

proc game {name infile outfile} {
    set in [open $infile r]
    set out [open $outfile w]
    set header [split [gets $in] ,]
    while {[gets $in line] > 0} {
        foreach col $header val [split $line ,] {
            puts -nonewline $out "$col: $val "
        }
        puts $out ""
    }
    close $in
    close $out
}

game foo input.csv output.txt

您可以使用 dict 来存储 csv 文件的数据:

proc game {name inFile} {
    upvar csv_data csv_data        
    set csv [open $inFile r]
    set csv_lines [read $csv]

    set row 0

    foreach line [split $csv_lines "\n"] {
        set values [split $line ","]
        for {set col 0} {$col < [llength $values]} {incr col} {
            dict set csv_data $row [expr {$col+1}] [string trim [lindex $values $col]]
        }
        incr row
    }

    close $csv
}

set csv_data {}
game foo input.csv

现在你可以像下面这样从字典中读取,其中第 0 行包含 headers,第 1 列是 a 作为 header:

# To get row 2 col 5:
puts [dict get $csv_data 2 5]
# => slow

# To get row 1 col 3:
puts [dict get $csv_data 1 3]
# => 100

要以您要求的其他格式打印,您需要做更多的工作:

set outFile [open output.txt w]
for {set row 1} {$row < [llength [dict keys $csv_data]]} {incr row} {
    set lineOut ""
    foreach {- header} [dict get $csv_data 0] {- value} [dict get $csv_data $row] {
        lappend lineOut "$header: $value"
    }
    puts $outFile [join $lineOut " "]
}
close $outFile

output.txt:

a: S b: 1.0 c: 100 d: F e: fast  
a: T b: 2.0 c: 200 d: S e: slow

你可能会:

package require csv

proc splitline {fh} {
    if {[gets $fh line] != -1} {
        set fields [csv::split $line]
        return [lmap field $fields {string trimleft $field}]
    }
}

proc transform {file} {
    set fh [open $file r]
    set head [splitline $fh]
    while {[set fields [splitline $fh]] ne ""} {
        puts [join [lmap h $head f $fields {string cat $h ":" $f}]]
    }
    close $fh
}

transform "file.csv"
a:S b:1.0 c:100 d:F e:fast
a:T b:2.0 c:200 d:S e:slow