我是tcl的新手,想要学习,需要下面的帮助。 我的字符串在configFileBuf中看起来像尝试用XYZ替换第二次出现的ConfENB:local-udp-port> 31001“,但是在我尝试的regsub cmd下面总是替换为第一次出现(37896).Plz帮助如何替换第二次出现与xyz。
set ConfigFileBuf "<ConfENB:virtual-phy>
</ConfENB:local-ip-addr>
<ConfENB:local-udp-port>37896</ConfENB:local-udp-port>
</ConfENB:local-ip-addr>
<ConfENB:local-udp-port>31001</ConfENB:local-udp-port>
</ConfENB:virtual-phy>"
regsub -start 1 "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>" $ConfigFileBuf "XYZ" ConfigFileBuf
puts $ConfigFileBuf
答案 0 :(得分:1)
您必须使用regexp -indices
来查找替换位置,然后才regsub
。如果将正则表达式放在自己的变量中,那就太糟糕了。
set RE "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>"
set start [lindex [regexp -all -indices -inline $RE $ConfigFileBuf] 1 0]
regsub -start $start RE $ConfigFileBuf "XYZ" ConfigFileBuf
1
是RE中的子匹配数(在这种情况下为零)加1.您可以在regexp -about
的帮助下计算它,给出这一点诡计:
set RE "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>"
set relen [expr {1 + [lindex [regexp -about $RE] 0]}]
set start [lindex [regexp -all -indices -inline $RE $ConfigFileBuf] $relen 0]
regsub -start $start RE $ConfigFileBuf "XYZ" ConfigFileBuf
答案 1 :(得分:0)
如果您的字符串是格式良好的XML,我建议使用tDOM来操作它。 DOM样式的操作几乎总是比基于正则表达式的XML标记操作更好。 (我之所以提到它实际上应该是XML并且你引用它错了。)
您似乎正在尝试使用-start 1
告诉regsub
跳过第一场比赛。起始索引实际上是一个字符索引,因此在此调用中regsub
将跳过字符串中的第一个字符。您可以将-start
进一步设置为字符串,但除非您使用regexp
来计算第一个匹配项的结束位置,否则这很脆弱。
我认为最好的解决方案是通过使用regexp
调用-all -inline -indices
来获取匹配的索引列表,使用lindex
选择第二个索引对,最后使用{{1执行替换,如下所示:
string replace
变量set pattern {</ConfENB:local-ip-addr>[ \n\t]+<ConfENB:local-udp-port>[0-9 ]+</ConfENB:local-udp-port>}
set matches [regexp -all -inline -indices -- $pattern $ConfigFileBuf]
set match [lindex $matches 1]
set ConfigFileBuf [string replace $ConfigFileBuf {*}$match XYZ]
包含要替换的字符范围的一对索引(分别为start和end)。由于match
期望这些索引位于不同的参数中,因此您需要使用string replace
前缀展开$match
。如果您的Tcl早于V的版本低于8.5,则需要稍微更改上述代码:
{*}
顺便提一下,请注意您可以避免逃避,例如正则表达式中的字符集,如果用括号而不是双引号引用它。