我可以这样做但是我的方法很笨拙,因为需要打开文件,读取文件,拆分成所有行,重新组合但没有第1行,最后保存文件。
由于这些文本文件可以是大型数据文件,因此要避免(缩短)所有这些处理步骤。也许有人知道更短或更光滑的方式吗?
非常诚挚的谢意!
答案 0 :(得分:1)
如果你的文件非常大,你实际上必须逐行处理它们,但如果它们只是一个GB左右,你可以通过将内容作为一个块来处理来简化处理数据。
package require fileutil
fileutil::updateInPlace file.ext {apply {data {
regsub {.*?\n} $data {}
}}}
updateInPlace
命令采用文件名和命令前缀。它打开文件,读取内容,并以内容作为参数调用命令前缀:最后,它将文件内容替换为调用的结果。在这种情况下,命令前缀是apply
命令和执行工作的匿名函数( lambda )。
编写相同内容的另一种(大多数是等同的)方法是使用命名命令过程:
proc cmd data {
regsub {.*?\n} $data {}
}
fileutil::updateInPlace file.ext cmd
命令/ lambda的主体可以是删除文本中第一个换行符之前的所有文本的任何内容,例如
regsub {[^\n]*\n} $data {}
与上面相同(将匹配的文本替换为第一个换行符),但是使用贪婪的匹配
string range $data [string first \n $data]+1 end
找到第一个换行符的索引并执行后面的所有内容
join [lrange [split [string trimright $data] \n] 1 end] \n
获取一个行列表并构建一个新文本,其中包含除第一行之外的所有行。
不同的变体并不完全相同。如果文件中没有换行符,则regsub
和string range
变体不会进行任何更改,但lrange
变体会将内容设置为空字符串。
文档:apply,fileutil包,join,lrange,package,proc,Syntax of Tcl regular expressions,{{ 3}},regsub,split
答案 1 :(得分:1)
对于一个非常大的文件(在现代机器上,它必须至少500MB才能进入这个类别),你真的你可以做的很多东西可以缩短你正在处理移动大量数据。您有移动数据以删除第一行。 (您可以通过截断来删除末尾的行。)
但是你可以做一些能加快速度的技巧。特别是,以兆字节大小的块为单位移动数据要快得多。这样可以充分利用seek
和tell
,并以chan truncate
结束。
# Open in read-write mode
set f [open $filename r+]
# Read in the stuff we want to delete; reading is easiest way to find end of line
gets $f
##### HOW TO COPY REMAINDER OF FILE TO EARLIER IN FILE #####
set target 0; # Start of file
fconfigure $f -translation binary
set source [tell $f]
while true {
# Read a megabyte (1024*1024 bytes) from the source position in the file
seek $f $source
set data [read $f 1048576]
set source [tell $f]; # Remember for next iteration
# If we didn't read anything, we're done.
if {[string length $data] == 0} {
break
}
# Write the data to the target location in the file. May overlap with where we
# read from, but won't go past end. (IMPORTANT!)
seek $f $target
puts -nonewline $f $data
set target [tell $f]; # Remember for next iteration
}
# Ensure there's nothing left over at the end
chan truncate $f $target
close $f
正如您所看到的,只需将所有内容读入内存,操作内容然后再将其写出来实际上更容易编码并且更简单的代码,以便失败不会破坏文件。 (你也可以一次流处理一行,写出一个新的临时文件,扩展到非常大,但它需要首先有额外的磁盘空间。)记住,唯一真正容易做的事情到一个大文件是附加到它。
如果可能,最好将非常大的数据集放入数据库中。这是对您的代码进行更广泛的更改。