[英]Extract contents of line from file given the line number in TCL
我知道这个问题是在 perl 和 grep 的上下文中提出的,但我想知道这是否可以使用 TCL。
目前我正在使用 scanmatch 命令在文本文件中查找特定的正则表达式。 我看到数组元素 matchInfo(linenum) 提供了匹配行的行号。 给定这个行号作为索引,我想提取子序列行的内容。
我想知道是否有一个 function 允许按行号提取行内容。
作为参考,我关注这个页面http://www.ucolick.org/~de/book/scan.html
谢谢!
阅读该页面表明matchinfo(offset)
将是最合适的。
如果你有
scanmatch $scanContext "some pattern" {nextLines 5 $fileName $matchinfo(offset)}
所以nextLines
可能会返回下一行。 这里的魔力是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)
而不是文件名来进行实验,并直接读取接下来的几行(无需查找)。 但是,如果文件中的 position 被其他代码更改,我不知道扫描文件将如何反应。
只是做了一些快速的实验,如果您提前阅读 scanmatch 代码,scanfile 不会受到打扰。 scanfile 将在文件中的新位置拾取。 这类似于在 awk 代码中使用getline
。
我不打算发布 necropost,但scanmatch
& friends 可以很容易地在脚本级别进行近似或重新实现。 通过研究TclX 来源,我得出了处理一个匹配的第一个近似值:
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]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.