如何解决给定 TCL 中的行号,从文件中提取行的内容
我知道这个问题是在 perl 和 grep 的上下文中提出的,但我想知道是否可以使用 TCL。
目前我正在使用 scanmatch 命令在文本文件中查找特定的正则表达式。我看到数组元素 matchInfo(linenum) 提供了匹配行的行号。将此行号作为索引,我想提取子序列行的内容。
我想知道是否有允许通过行号提取行内容的函数。
作为参考,我正在关注此页面 http://www.ucolick.org/~de/book/scan.html
谢谢!
解决方法
通读该页面表明 matchinfo(offset)
是最合适的。
如果你有
scanmatch $scanContext "some pattern" {nextLines 5 $fileName $matchinfo(offset)}
所以 nextLines
或许可以返回下一个 number 行。这里的神奇之处在于 seek
命令可以直接跳到匹配的行。
proc nextLines {numLines fileName offset} {
set fid [open $fileName r]
seek $fid $offset
for {set i 0} {$i < $numLines} {incr i} {
if {[gets $fid line] == -1} break
lappend lines $line
}
close $fid
return $lines
}
您可以通过传递 $matchinfo(handle)
而不是文件名进行实验,并直接读取接下来的几行(无需查找)。但是,如果其他代码更改了文件中的位置,我不知道 scanfile 会如何反应。
刚刚做了一些快速实验,如果您提前阅读 scanmatch 代码,则不会打扰 scanfile。 scanfile 将在文件中的新位置拾取。这类似于在 awk 代码中使用 getline
。
我不打算进行 necropost,但是 scanmatch
和朋友可以很容易地在脚本级别近似或重新实现。通过研究 TclX sources,我得出了处理一个匹配的第一个近似值:
proc scanMatchOnce {filePath pattern handler} {
set ch [open $filePath r]
try {
while {1} {
set offset [chan tell $ch]
if {[chan gets $ch line] < 0 || [eof $ch]} {
break
} elseif {[regexp $pattern $line]} {
apply [list {linestart lineend fileName} $handler ::] $offset [chan tell $ch] $filePath
break
} else {
continue
}
}
} finally {
catch {chan close $ch}
}
return
}
这可以轻松扩展以提供扫描上下文、扫描匹配链等。实现的关键是尽早使用 chan tell
来捕获行开始处的偏移量等。
该实现并不意味着与 TclX 的扫描实用程序兼容。
将其与 glenn 的示例一起使用,例如:
scanMatchOnce $someFilePath {some Pattern} {puts [nextLines 5 $fileName $linestart]}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。