有没有办法使用regsub进行多次替换?

时间:2012-11-06 21:38:44

标签: regex tcl

是否可以使用regsub在表达式中进行不同的替换?

示例:

set a ".a/b.c..d/e/f//g"

现在,在这个表达式中,是否可以替换 “.”为“yes”  “..”为“no”  “/”为“true”  单个regsub命令中的“//”为“false”?

2 个答案:

答案 0 :(得分:8)

regsub,没有。对于这种事情有一个长期的功能请求(需要用匹配信息评估命令的结果替换)但是到目前为止它还没有被采取行动。

但在这种情况下,你可以使用string map做你想做的事情:

set a ".a/b.c..d/e/f//g"
set b [string map {".." "no" "." "yes" "//" "false" "/" "true"} $a]
puts "changed $a to $b"
# changed .a/b.c..d/e/f//g to yesatruebyescnodtrueetrueffalseg

请注意,在构建地图时,如果任何from-value是另一个的前缀,则应首先放置较长的from-value。 (这是因为string map实现会按照您在...中列出的顺序检查要进行的更改。)


可以使用regsubsubst在两个步骤中进行多目标替换,但除了非常复杂的情况之外,我不建议使用它!一个不错的string map更容易使用。

答案 1 :(得分:2)

您也可以尝试自己动手。这是一个草案proc,您可以将其作为起点。它不是生产准备好的,你必须小心,因为第一个之后的替换处理已经被替换的字符串。

这些是参数:

  • options是一个选项列表,将传递给每次调用regsub
  • resubList是键/值对的列表,其中键是正则表达式,值是替换
  • string是您要替换的字符串

这是程序,它只是多次调用regsub,对resubList中的每个元素调用一次,最后返回最后一个字符串。

proc multiregsub {options resubList string} {
    foreach {re sub} $resubList {
        set string [regsub {*}$options -- $re $string $sub]
    }
    return $string
}