我有一个VHDL文件,其行如下:
constant version_nr :integer := 47;
我想在文件中增加此行中的数字。有没有办法用TCL来实现这个目标?
答案 0 :(得分:2)
这主要是一个字符串操作。棘手的一点是找到要操作的线并从中挑出数字。这可能偶尔会很尴尬,但主要是选择合适的正则表达式(因为这是他们擅长的解析任务)。进行匹配的原始RE是:
^\s*constant\s+version_nr\s*:integer\s*:=\s*\d+\s*;\s*$
这实质上是将空白序列的所有可能位置转换为\s*
(除非必须使用空格,后者变为\s+
)并将数字与\d+
匹配,即数字序列。然后我们在括号中添加 capture 有趣的子串,它们是前缀,数字和后缀:
^(\s*constant\s+version_nr\s*:integer\s*:=\s*)(\d+)(\s*;\s*)$
现在我们已经足够进行行转换(我们将作为一个程序执行,因此我们可以给它一个好名字):
proc lineTransform {line} {
set RE {^(\s*constant\s+version_nr\s*:integer\s*:=\s*)(\d+)(\s*;\s*)$}
if {[regexp $RE $line -> prefix number suffix]} {
# If we match, we increment the number...
incr number
# And reconcatenate it with the prefix and suffix to make the new line
set line $prefix$number$suffix
}
return $line
}
在Tcl 8.7(您还没有使用)中,您可以将其写成更简洁的形式:
proc lineTransform {line} {
# Yes, this version can be a single (long) line if you want
set RE {^(\s*constant\s+version_nr\s*:integer\s*:=\s*)(\d+)(\s*;\s*)$}
regsub -command $RE $line {apply {{- prefix number suffix} {
# Apply the increment when the RE matches and build the resulting line
string cat $prefix [incr number] $suffix
}}}
}
现在我们有了一个行变换,我们只需将它应用于文件的所有行。这可以通过适合内存的文件(最多几百MB)轻松完成,但需要对较大文件采取额外措施,因为您需要从一个文件流式传输到另一个文件:
proc transformSmallFile {filename} {
# Read data into memory first
set f [open $filename]
set data [read $f]
close $f
# Then write it back out, applying the transform as we go
set f [open $filename w]
foreach line [split $data "\n"] {
puts $f [transformLine $line]
}
close $f
}
proc transformLargeFile {filename} {
set fin [open $filename]
# The [file tempfile] command makes working with temporary files easier
set fout [file tempfile tmp [file normalize $filename]]
# A streaming transform; requires that input and output files be different
while {[gets $fin line] >= 0} {
puts $fout [transformLine $line]
}
# Close both channels; flushes everything to disk too
close $fin
close $fout
# Rename our temporary over the original input file, replacing it
file rename $tmp $filename
}