从文本文件中读取特定列的数据并写入另一个文本文件 tcl

Reading specific column of data from text file and write to another text file tcl

通过使用 Tcl。例如,我有数据

hello;world;123
test;code;456

我只想获取第一列的值并将其写入另一个文本文件。输出将是这样的。

hello
test

您只需从输入文件中读取:

set pfi [open "file_name" "r"]
set cnt [gets $pfi row]

然后过滤第一个词:

set word [lindex [split $row ";"] 0]

然后写入输出文件

set pfo [open "file_out_name" "w"]
puts $pfo $word

您可以使用 cnt 来判断文件是否结束(当 cnt < 0 时文件结束),这样您就可以遍历文件的所有行。当然,最后还是要关闭文件的:

close $pfi
close $pfo

因此,合并所有步骤:

set pfi [open "file_in_name" "r"]
set pfo [open "file_out_name" "w"]
while {1 == 1} {
    set cnt [gets $pfi row]
    if {$cnt < 0} {break}
    set word [lindex [split $row ";"] 0]
    puts $pfo $word
}
close $pfi
close $pfo

嗯嗯...

有几种方法可以做到这一点。如果您在类 unix 平台上,cut 命令是正确的方法,从 Tcl 内部或 shell 脚本。当然,Tcl 也可以做到这一点,尽管不那么方便(脚本很难与实用程序竞争)。

最简单的解决方案利用 fileutil,世界上最被低估的软件包之一:

package require fileutil
namespace import ::fileutil::*

一个命令,foreachLine,让我们为文件中的每一行做一些事情(data.old):

foreachLine line data.old {appendToFile data.new [lindex [split $line \;] 0]\n}

我们在这里所做的是将每一行的搜索词附加到另一个文件 (data.new)。

我们还可以就地编辑文件,借助将文件内容分成多行的命令,将每行截断为第一个子字符串,最多分号,然后重新加入各行:

proc cmd data {
    join [lmap line [split [string trim $data] \n] {
        lindex [split $line \;] 0
    }] \n
}

然后我们来做(注意这里是替换原来的内容):

updateInPlace data.old cmd

这有点复杂,但对于不是严格逐行的操作来说很实用。

另外几个包对字符分隔数据很有帮助:csv 导入数据集,struct::matrix 操作数据。

package require csv
package require struct::matrix

::struct::matrix m

将数据导入矩阵m(因为包的定义方式,这里需要处理通道):

set old [open data.old]
::csv::read2matrix $old m \; auto
chan close $old

获取矩阵的第一列:

set data [m get column 0]

将截断的数据写入文件:

writeFile data.new [join $data \n]

当然也可以以低级别的核心 Tcl 方式执行此操作。此解决方案类似于 Andrea Tosoni 的解决方案,但更加地道。

set old [open data.old]
set new [open data.new w]
while {[chan gets $old line] >= 0} {
    chan puts $new [lindex [split $line \;] 0]
}
chan close $old
chan close $new

文档:chan, csv package, fileutil package, join, lappend, lindex, lmap, lmap replacement, namespace, open, package, set, split, struct::matrix package, while