用Tcl解析文件

用Tcl解析文件,tcl,Tcl,我这里有一个文件,它有多个set语句。然而,我想提取我感兴趣的线条。下面的代码有帮助吗 set in [open filename r] seek $in 0 start while{ [gets $in line ] != -1} { regexp (line to be extracted) } 首先,您不需要在打开一个文件进行读取后直接查找;这就是它的起点 其次,读取文件的模式如下: set f [open $filename] while {[gets

我这里有一个文件,它有多个set语句。然而,我想提取我感兴趣的线条。下面的代码有帮助吗

set in [open filename r]    
seek $in 0 start    
while{ [gets $in line ] != -1} {    
    regexp (line to be extracted)
}

首先,您不需要在打开一个文件进行读取后直接
查找
;这就是它的起点

其次,读取文件的模式如下:

set f [open $filename]
while {[gets $f line] > -1} {
    # Process lines
    if {[regexp {^set +(\S+) +(.*)} $line -> name value]} {
        puts "The name \"$name\" maps to the value \"$value\""
    }
}
close $f
<>当然,这是中间的一个非常简单的RE(对于更复杂的文件,你需要几个),但是这是一般的模式。请注意,与Tcl一样,while命令词后面的空格很重要,while表达式和while主体之间的空格也很重要。有关特定类型输入数据的RE使用方法的具体帮助,请在此询问有关堆栈溢出的更多问题。

其他解决方案:

与使用
gets
相比,我更喜欢使用
read
函数读取文件的全部内容,然后逐行处理这些内容。因此,我们通过将文件作为行列表来完全控制对文件的操作

set fileName [lindex $argv 0]
catch {set fptr [open $fileName r]} ;
set contents [read -nonewline $fptr] ;#Read the file contents
close $fptr ;#Close the file since it has been read now
set splitCont [split $contents "\n"] ;#Split the files contents on new line
foreach ele $splitCont {
    if {[regexp {^set +(\S+) +(.*)} $ele -> name value]} {
        puts "The name \"$name\" maps to the value \"$value\""
    }
}
如何运行此代码:
假设上述代码保存在
test.tcl

然后


FileName
是文件的完整路径,除非文件位于程序所在的同一目录中。

这里还有另一个解决方案:使用Tclx的文件扫描功能。有关更多信息,请查阅Tclx。我喜欢这个解决方案,因为你可以有几个扫描匹配块

package require Tclx

# Open a file, skip error checking for simplicity
set inputFile [open sample.tcl r]

# Scan the file 
set scanHandle [scancontext create]
scanmatch $scanHandle {^\s*set} {
    lassign $matchInfo(line) setCmd varName varValue; # parse the line
    puts "$varName = $varValue"
}
scanfile $scanHandle $inputFile
close $inputFile
另一种解决方案:使用fileutil包中的grep命令:

package require fileutil

puts [lindex $argv 0]
set matchedLines [fileutil::grep {^\s*set} [lindex $argv 0]]
foreach line $matchedLines {
    # Each line is in format: filename:line, for example
    # sample.tcl:set foo bar
    set varName [lindex $line 1]
    set varValue [lindex $line 2]
    puts "$varName = $varValue"
}
另一种解决方案:


由于源代码看起来像是一个TCL脚本,请使用它创建一个新的安全解释器,该解释器只显示set命令(以及您需要的任何其他命令),隐藏所有其他命令,并替换为跳过任何未识别的命令。到目前为止,我已经阅读了您的注释,如果我理解正确,您的输入数据文件每行有6个(或9个,取决于哪个注释)数据字段,用空格分隔。您希望使用regexp将它们解析为6(或9)个数组或列表,每个数据字段一个

如果是这样的话,我会尝试这样的方法(使用列表):

现在,您应该有一组6个列表,每个字段一个,列表中的每个条目对应于输入文件中的每个项目。例如,要访问第i个名称,您可以抓取
$nameL[$i
]

如果(如我所怀疑的)您的主要目标是获取名称为“foo”的设备的参数,您将使用如下结构:

set name "foo"
set i [lsearch $nameL $name]
if {$i != -1} {
    set source $sourceL[$i]
} else {
    puts "item $name not found."
    set source ''  
    # or set to 0, or whatever "not found" marker you like
}

我有如下几行。。。。。。设置名称某些字符串设置其他名称某些其他字符串。。。。及soon@Nazeeb:尝试上面更改的版本。拆分行,以便获得
$name
$value
。我的样本只是打印出来;添加代码来做一些更智能的事情…要提取的行是。。。。。。“男人对女人0.90.09”。。。我认为regexp不可能在TCL中使用脚本而不是TCLx@Nazeeb:这仍然是TCL,但有Tclx包的帮助。如果您不想使用Tclx,请查看其他解决方案。我希望我正确理解了你的问题。要摘录的行是。。。。。。“男人对女人0.90.09”。。。我认为regexp不起作用。在运行程序时,您是否已将文件名作为参数?错误就在那里,因为open函数没有找到该文件。@Nazeeb从“man.poi o a vs s 0.9 0.09”中提取的确切内容是什么?@Vaichidrewr:整行必须extracted@vaichidrewar如果要使用拆分结果,请使用read的-nonewline开关\n。否则,如果文件以换行符结尾,则在行列表的末尾会有一个额外的空“false”元素。
set f [open $filename]
while {[gets $f line] > -1} {
    # Process lines
    if {[regexp {(\S+) (\S+) (\S+) (\S+) (\S+) (\S+)} $line -> name source drain gate bulk inst]} {
        lappend nameL $name
        lappend sourceL $source
        lappend drainL $drain
        lappend gateL $gate
        lappend bulkL $bulk
        lappend instL $inst
    }
}
close $f
set name "foo"
set i [lsearch $nameL $name]
if {$i != -1} {
    set source $sourceL[$i]
} else {
    puts "item $name not found."
    set source ''  
    # or set to 0, or whatever "not found" marker you like
}
set File [ open $fileName r ]

  while { [ gets $File line ] >= 0 } {

 regex {(set) ([a-zA-Z0-0]+) (.*)} $line str1 str2 str3 str4

   #str2 contains "set";
   #str3 contains variable to be set;
   #str4 contains the value to be set;

  close $File
 }