在regsub中传递一个匹配&一个程序(正在使用Tcl)

时间:2015-07-06 20:34:11

标签: regex tcl

我想通过逗号分隔的字符串,并用更多逗号分隔的元素替换匹配。

即5-A,在regsub之后的B应该给我1-A,2-A,3-A,4-A,5-A,B

以下对我来说不适用于&正在作为一个实际的&而不是实际匹配:

regsub -all {\d+\-\w+} $string [myConvertProc &]

然而,并没有试图通过&直接使用它:

regsub -all o "Hello World" &&&
> Hellooo Wooorld

在尝试传递价值&时,不确定我做错了什么坚持 myConvertProc

编辑: 我认为我最初的问题是[myConvertProc&]首先得到评估,所以我实际上正在传递'&'该程序。

如何在正则表达式领域解决这个问题?有可能吗?

编辑2: 我已经在拆分列表中使用foreach解决了它,所以我只是想在regsub中查看这是否可行。谢谢!

1 个答案:

答案 0 :(得分:3)

你的第一次编辑是正确的:问题是在执行命令之前,regsub的每个参数都被完全评估。

一种解决方案是在字符串中插入命令替换字符串,然后在其上使用subst

set string [regsub -all {\d+\-\w+} $string {[myConvertProc &]}]
# -> [myConvertProc 5-A],B
set string [subst $string]
# -> 1-A,2-A,3-A,4-A,5-A,B

只有在string中没有其他内容可以替换时才会有效(但您当然可以关闭变量和反斜杠替换)。

foreach解决方案要好得多。另一种foreach解决方案是迭代regexp -indices -inline -all的结果,但如果它有效,则迭代分割列表的各个部分是可取的。

<强>更新

典型的foreach解决方案如下:

set res {}
foreach elem [split $string ,] {
    if {[regexp -- {^\d+-\w+$} $elem]} {
        lappend res [myConvertProc $elem]
    } else {
        lappend res $elem
    }
}
join $res ,

也就是说,通过查看原始列表中的每个元素来收集结果列表。如果元素符合您的要求,则转换它并将结果添加到结果列表中。如果元素不匹配,只需将其添加到结果列表中即可。

在Tcl 8.6中可以稍微简化一下:

join [lmap elem [split $string ,] {
    if {[regexp -- {^\d+-\w+$} $elem]} {
        myConvertProc $elem
    } else {
        set elem
    }
}] ,

这是一回事,但lmap命令会为您处理结果列表。

文档:foreachlappendlmapregexpregsubsetsplit,{{3 }}