从CSV文件中读取

时间:2016-08-09 05:09:21

标签: csv tcl

我有一个CSV文件,其中包含许多行和列2,其中类似于:

 Horizontal-1 Acc. Filename      Horizontal-2 Acc. Filename
 RSN88_SFERN_FSD172.AT2          RSN88_SFERN_FSD262.AT2 
 RSN164_IMPVALL.H_H-CPE147.AT2   RSN164_IMPVALL.H_H-CPE237.AT2 
 RSN755_LOMAP_CYC195.AT2         RSN755_LOMAP_CYC285.AT2 
 RSN1083_NORTHR_GLE170.AT2       RSN1083_NORTHR_GLE260.AT2 
 RSN1614_DUZCE_1061-N.AT2        RSN1614_DUZCE_1061-E.AT2 
 RSN1633_MANJIL_ABBAR--L.AT2     RSN1633_MANJIL_ABBAR--T.AT2 
 RSN3750_CAPEMEND_LFS270.AT2     RSN3750_CAPEMEND_LFS360.AT2 
 RSN3757_LANDERS_NPF090.AT2      RSN3757_LANDERS_NPF180.AT2
 RSN3759_LANDERS_WWT180.AT2      RSN3759_LANDERS_WWT270.AT2 
 RSN4013_SANSIMEO_36258021.AT2   RSN4013_SANSIMEO_36258111.AT2 
 RSN4841_CHUETSU_65004NS.AT2     RSN4841_CHUETSU_65004EW.AT2 
 RSN4843_CHUETSU_65006NS.AT2     RSN4843_CHUETSU_65006EW.AT2 
 RSN4844_CHUETSU_65007NS.AT2     RSN4844_CHUETSU_65007EW.AT2 
 RSN4848_CHUETSU_65011NS.AT2     RSN4848_CHUETSU_65011EW.AT2 

在CSV文件中,我想查找标题“Horizo​​ntal-1 Acc.Filename和Horizo​​ntal-2 Acc.Filename”,然后逐行获取这些标题下每行的名称一次?

有什么建议吗?

由于 RG。

2 个答案:

答案 0 :(得分:1)

package require csv
package require struct::matrix

::struct::matrix m
m add columns 2

set chan [open data.csv]
::csv::read2matrix $chan m
close $chan

lassign [m get row 0] header1 header2

for {set r 1} {$r < [m rows]} {incr r} {
    puts -nonewline [format {%s = %-30s  } $header1 [m get cell 0 $r]]
    puts [format {%s = %s} $header2 [m get cell 1 $r]]
}

m destroy

我发现处理csv数据集的最简单方法是使用matrixmatrix是一种二维向量,带有用于搜索,排序和重新排列列和行的内置函数。

首先,创建一个矩阵并将其命名为m。它从头开始有两列,但还没有行。

::struct::matrix m
m add columns 2

打开一个频道来读取数据文件。将通道和矩阵名称传递给::csv::read2matrix命令。此命令将读取csv数据并为每个数据行创建矩阵行。数据字段存储在列中。

set chan [open data.csv]
::csv::read2matrix $chan m
close $chan

要获取标题字符串,请检索第0行。

lassign [m get row 0] header1 header2

要迭代数据行,请从1(如果我们没有标题,0)到m rows下面,这是矩阵中的行数。

有一个方便的report工具适用于矩阵,但我在这里只使用for循环。我猜你想要的数据是什么:

for {set r 1} {$r < [m rows]} {incr r} {
    puts -nonewline [format {%s = %-30s  } $header1 [m get cell 0 $r]]
    puts [format {%s = %s} $header2 [m get cell 1 $r]]
}

如果你已完成矩阵,你也可以将其销毁。

m destroy

评论中特定问题的解决方案。

package require csv
package require struct::matrix

::struct::matrix m

set chan [open foo.csv]
::csv::read2matrix $chan m , auto
close $chan

set f1 [m search column 0 "Result ID"]
set headerRow [lindex $f1 0 1]
set f2 [m search rect 0 $headerRow 0 [expr {[m rows] - 1}] ""]
set f3 [m search row $headerRow "Horizontal-1 Acc. Filename"]
set f4 [m search row $headerRow "Horizontal-2 Acc. Filename"]

set top [expr {$headerRow + 1}]
set bottom [expr {[lindex $f2 0 1] - 1}]
set left [lindex $f3 0 0]
set right [lindex $f4 0 0]

puts [format {Vector=[ %s ]} [concat {*}[m get rect $left $top $right $bottom]]]
m destroy

显然,您需要将文件名更改为正确的名称。没有错误处理:在这样一个简单的脚本中,最好让脚本失败并纠正错误。

解决第二个问题,评论如下:

package require csv
package require struct::matrix

::struct::matrix m

set chan [open _SearchResults.csv]
::csv::read2matrix $chan m , auto
close $chan

set f1 [m search column 0 {Result ID}]
set headerRow [lindex $f1 0 1]

set f2 [m search -glob rect 0 $headerRow 0 [expr {[m rows] - 1}] { These*}]
set numofRow [lindex $f2 0 1]

set headercol1 [m search row $headerRow { Horizontal-1 Acc. Filename}]
set headercol2 [m search row $headerRow { Horizontal-2 Acc. Filename}]  

set indexheaderH1col [lindex $headercol1  0 0]
set indexheaderH2col [lindex $headercol2  0 0]

set rows [m get rect $indexheaderH1col [expr {$headerRow+1}] $indexheaderH2col [expr {$numofRow-1}]]

set rows [lmap row $rows {
    lassign $row a b
    list [string trim $a] [string trim $b]
}]

foreach row $rows {
    puts [format {%-30s   %s} {*}$row]
}

puts [format {Vector=[ %s ]} [concat {*}$rows]]

评论:

  • 如果read2matrix使用auto
  • ,则无需设置列数
  • 在此文件中,表后没有空单元格。相反,我们需要搜索以“These”
  • 开头的字符串
  • 由于每个单元格都有一个空格字符后跟值,我们需要修剪值周围的空格,否则连接会出错。具有lmap命令的部分修复了
  • Always brace your expressions

文档: + (operator)- (operator)< (operator)chancloseconcatcsv (package)exprforformatincrlassignlindexlmap (for Tcl 8.5)lmapopenpackageputssetstruct::matrix (package){*} (syntax)

答案 1 :(得分:0)

擦除所有

package require csv
package require struct::matrix

::struct::matrix m
m add columns 2

set chan [open _SearchResults.csv]
::csv::read2matrix $chan m  , auto
close $chan

set f1 [m search column 0 {Result ID}]
set headerRow [lindex $f1 0 1]

set f2 [m search rect 0 $headerRow 0 [expr {[m rows] - 1}] {}]
set  numofRow [lindex [lindex $f2 0 1]]

set headercol1 [m search row  $headerRow { Horizontal-1 Acc. Filename}]
set headercol2 [m search row  $headerRow  { Horizontal-2 Acc. Filename}]  

set indexheaderH1col [lindex $headercol1  0 0]
set indexheaderH2col [lindex $headercol2  0 0]

set header1 [m get cell $indexheaderH1col $headerRow]
set header2 [m get cell $indexheaderH2col $headerRow]

for {set r [expr $headerRow+1]} {$r < [expr $numofRow-1]} {incr r} {
    puts [format {%-30s   %s}  [m get cell $indexheaderH1col $r]  [m get cell $indexheaderH2col $r]]
}

set  vector   [concat {*}[m get rect $indexheaderH1col  [expr $headerRow+1] $indexheaderH2col [expr $numofRow-1]]]

puts [format {Vector=[ %s ]} [concat {*}[m get rect $indexheaderH1col  [expr $headerRow+1] $indexheaderH2col [expr $numofRow-1]]]]