从文件中拆分一行以替换 tcl 中的元素 [英] Split a line from a file to replace elements in tcl
问题描述
我正在尝试执行以下操作:
I'm trying to do the following:
- 打开文件读取
- 分割线
- 确定感兴趣的线路
- 将名称
Prefix_2
替换为Prefix_999
- 删除所有带有
Prefix_1
的行 - 将行保存到原始文件
我最多可以做第 3 点,但是在替换名称时,我似乎无法将感兴趣的行拆分为元素,以便我可以用 Prefix_999
替换 Prefix_2
>
I can do up to point 3 but when it comes to replacing the names I cant seem to split the line of interest into elements so that I can replace Prefix_2
with Prefix_999
它总是替换为整个感兴趣的行,如下所示,例如
It always replaces with entire line of interest as shown below e.g.
Prefix_2.Var1 = 5124
将替换为 Prefix_999
而不是 Prefix_999.Var1 = 5124
Prefix_2.Var1 = 5124
will replace to Prefix_999
rather than Prefix_999.Var1 = 5124
文件Data.txt
Prefix_1.Var1 = 200
Prefix_1.Var2 = 0.3
Prefix_1.Var3 = 0.5
Prefix_1.Var4 = 0.25
Prefix_1.Var5 = 3
Prefix_1.Var6 = 36
Prefix_1.Var7 = 5612
Prefix_1.Var8 = 631
Prefix_1.Var9 = 102
Prefix_1.Var10 = 14
Prefix_1.Var11 = 3
Prefix_1.Var12 = 2
Prefix_2.Var1 = 5124
Prefix_2.Var2 = 876
Prefix_2.Var3 = 10.1
Prefix_2.Var4 = 11
我的代码:
set input [open "Data.txt" r]
set number 0
set var2 ""
while { [gets $input line] >= 0 } {
incr number
set sline [split $line "\n"]
set var1 [regexp {Prefix_2.Var1} $sline match]
if {$var1 == 1} {
set rVar1 [split $sline \s]
# check the length to index correctly for replacing
set rVar2 [llength $rVar1]
set rVar2 [lreplace $rVar2 0 0 Prefix_999.Var1]
}
}
close $input
推荐答案
由于您不是在编写文本过滤器,因此最好在更高级别上工作.
Since you're not writing a text filter, you might be better off working on a higher level.
proc processLine {bufName line} {
upvar 1 $bufName buf
switch -regexp $line {
{^Prefix_1\.} {}
{^Prefix_2\.} {
lappend buf [regsub 2 $line 999]
}
default {
lappend buf $line
}
}
}
package require fileutil
set buf {}
fileutil::foreachLine line data.txt {
processLine buf $line
}
fileutil::writeFile data.txt [join $buf \n]
较低级别的open
-gets
-close
组合是语言核心的一部分;fileutil
包可以用来抽象出这个组合的大多数用法,它是 Tcllib
的一部分,Tcl 的配套库.
The lower-level open
-gets
-close
combo is part of the language core; the fileutil
package that can be used to abstract away most usages of this combo is a part of Tcllib
, the companion library for Tcl.
我正在这里处理您的规范,因为您的代码有点难以理解.
I'm working with your specification here, since your code is a little hard to follow.
- 打开文件读取
- 分割线
- 确定感兴趣的线路
- 用 Prefix_999 替换 Name Prefix_2
- 删除所有带有 Prefix_1 的行
- 将行保存到原始文件
确定兴趣线
processLine
命令将接收参数line
中的每一行.switch -regexp $line {...}
命令让我可以通过前缀(或其他任何方式,标准可以是任何可以用正则表达式表达的东西)对行进行分类.行分为三类:以Prefix_1"开头的行、以Prefix_2"开头的行以及所有其他行.我将在持久缓冲区中保存行作为默认操作(在命令内部称为 buf
,在命令外部称为 $bufName
:在我的代码中,两个名称相同).
The processLine
command will be receiving each line in the parameter line
. The switch -regexp $line {...}
command lets me classify the lines, by prefix (or by whatever, the criteria can be anything that can be expressed by a regular expression). There are three classes of lines: those that start with "Prefix_1", those that start with "Prefix_2", and all other lines. I make it a default action to save lines in a persistent buffer (which is called buf
inside the command and $bufName
outside it: in my code both names are the same).
用 Prefix_999 替换 Name Prefix_2
对于以Prefix_2"开头的行,我跳过默认操作,而是保存修改后的行,其中第一次出现的 2 被 999 替换.
For lines that start with "Prefix_2", I skip the default action and instead save a modified line where the first occurrence of 2 is replaced by 999.
删除所有带有 Prefix_1 的行
只需跳过这些行的默认操作即可满足此要求.
This requirement is fulfilled simply by skipping the default action for these lines.
打开文件读取和分割线
这是由 fileutil::foreachLine
自动完成的.
This is done automatically by fileutil::foreachLine
.
将行保存到原始文件
我只是将缓冲区中的行与换行符连接起来,然后调用 fileutil::writeFile
来更新文件.
I simply join the lines in the buffer with newline characters and invoke fileutil::writeFile
to update the file.
ETA 没有 upvar
行处理命令不必直接访问行缓冲区;相反,它可以简单地返回行(跳过的行是空字符串).在这种情况下,需要在 foreachLine
的脚本参数中组装行缓冲区:
The line processing command doesn't have to access the line buffer directly; instead it can simply return lines (skipped lines being empty strings). In this case assembling the line buffer needs to be performed in the script argument to foreachLine
:
proc processLine line {
switch -regexp $line {
{^Prefix_1\.} {}
{^Prefix_2\.} {
regsub 2 $line 999
}
default {
return $line
}
}
}
package require fileutil
set buf {}
fileutil::foreachLine line data.txt {
set line [processLine $line]
if {$line ne {}} {
lappend buf $line
}
}
fileutil::writeFile data.txt [join $buf \n]
(我认为这个版本较差.)
(I'd rate this version as inferior.)
文档:fileutil 包的程序,if, join, lappend, 包, proc, regsub, 设置, switch, upvar
Documentation: fileutil package, if, join, lappend, package, proc, regsub, set, switch, upvar
这篇关于从文件中拆分一行以替换 tcl 中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!