繁体   English   中英

给定 TCL 中的行号,从文件中提取行的内容

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM