使用TCL可以“向后”读取文件

时间:2014-02-05 08:36:32

标签: file tcl

我有一个非常大的文本文件,我必须从中提取一些数据。我逐行阅读文件并查找关键字。据我所知,我正在寻找的关键字更接近文件末尾而不是开头,我想知道是否可以从最后一行而不是第一行开始读取文件。然后,我会使用一个aditional关键字来表示"这个词的所有内容都不是极端的"并停止阅读。

这可能吗?

5 个答案:

答案 0 :(得分:4)

我不知道这会有多高效,但是通过tac运行文件并从中读取:

set fh [open "|tac filename"]
# read from last line to first
while {[gets $fh line] != -1} {...

另一种策略是读取文件的最后一个,比如5000个字节(使用seek),拆分换行并检查这些行,然后寻找从最后位置10000并读取“下一个” 5000字节等

答案 1 :(得分:3)

不可能(在我所知的任何运行时/语言中,包括Tcl)。

因此,决定缓冲区并通过向后搜索并尝试每次读取完整缓冲区来读取文件。

请注意,您必须遵守某些可能性:

  • 文件可能小于缓冲区的大小。
  • 您似乎正在处理文本文件,并希望按行处理它。如果是这样,请注意如果代码是跨平台的或必须在Windows上工作,则必须处理上次读取操作中放置在缓冲区中的数据以LF开头的情况,以及下一个读取操作chunk-将以CR结束 - 也就是说,您的EOL标记将在缓冲区中分割。

    您可能需要查看Tcl source codeTcl_GetsObj()文件中generic/tclIO.c的实施情况 - 它会处理正常情况下的拆分CRLF("转发&#34) ;)从文件中读取文本字符串。

答案 2 :(得分:3)

获取文件末尾进行搜索的最简单方法是假设您不知道记录的大小(即行长度),而是抓住太多并使用它。

set f [open $filename]
# Pick some large value; the more you read, the slower
seek $f -100000 end
# Read to the end, split into lines and *DISCARD FIRST*
set lines [lrange [split [read $f] "\n"] 1 end]

现在您可以使用lsearch进行搜索。 (请注意,您不会确切地知道匹配行在文件中的位置;如果您需要,则需要做更多的工作。)

if {[lsearch -glob $lines "*FooBar*"] >= 0} {
    ...
}

从阅读部分丢弃第一行是因为你可能正在开始阅读中途的一半;放弃第一条“线”将意味着你只有真正的线路来处理。 (100kB对于任何现代计算机系统来说都不是很难搜索,但你可以进一步限制它。这取决于数据的细节。)

答案 3 :(得分:0)

package require struct::list

set fp [open "filename.txt"]
set lines [split [read -nonewline $fp] "\n"]
foreach line [struct::list reverse $lines] {
    ...
}

使用"$line"执行某些操作。

答案 4 :(得分:0)

要反转文件,我将文件读入变量“list”,逐行预先挂起$ list并显示当前行。这样List与文件的顺序相反..

while {[gets $in line] > -1} { 
   if [regexp "#" $line] {
      continue
   }
   # reverse the order in variable "list"
   set list "$line $list"
}

foreach line $list {
   puts "line:$ln line= $line" 
""*** process each line as you need ***""
}