【问题标题】:Passing a match in regsub with & to a procedure (Tcl is being used)将带有 & 的 regsub 匹配传递给过程(正在使用 Tcl)
【发布时间】:2015-09-24 03:30:03
【问题描述】:

我想检查一个逗号分隔的字符串,并用更多逗号分隔的元素替换匹配项。

即 regsub 之后的 5-A,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 中实现。谢谢!

【问题讨论】:

    标签: regex tcl


    【解决方案1】:

    您的第一次编辑是正确的:问题是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 命令会为您处理结果列表。

    文档:foreachlappendlmapregexpregsubsetsplitsubst

    【讨论】:

    • 感谢您的示例!我真的很喜欢命令替换,希望我自己想到它:) 在尝试 regbsub 之前我最终使用 foreach 做的是遍历拆分列表,然后 myConvertProc 将返回一个列表,我将 regsub 到我在 foreach 中的当前元素的位置。
    • @Gsavin:如果您使用foreach,则根本不需要regsub。请参阅我的更新答案。
    • 是的,我明白你的意思了!不过,我确实有后续行动。 regsub 不能一起用来代替 if/else 吗?对不起,如果它没有解决格式化。 (为了示例,myConvertProc 返回相同的元素,如果它没有格式 #-elem) foreach elem $splitList { regsub $elem $splitList [myConvertProc $elem] splitList }
    • @Gsavin:你当然可以这样做,但这不是最好的解决方案。它的一个问题是,随着splitList 的变化,插入的转换结果之一可能会意外地匹配elem 字符串之一(尝试使用列表5-A,4-A,B)。最好的做法是做最简单的事情:使用regsub 有很多潜在的复杂性。
    • 我倾向于不时避开最简单的解决方案 :)
    猜你喜欢
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2016-07-12
    相关资源
    最近更新 更多