用Tcl解析文件
我这里有一个文件,它有多个set语句。然而,我想提取我感兴趣的线条。下面的代码有帮助吗用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 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
}