如何使用regsub查找和替换第二次出现的字符串

时间:2014-06-20 08:01:47

标签: tcl

我是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

2 个答案:

答案 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,则需要稍微更改上述代码:

{*}

顺便提一下,请注意您可以避免逃避,例如正则表达式中的字符集,如果用括号而不是双引号引用它。

文档链接:regexplindexstring

相关问题