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