如何在tcl中调用函数的上下文中执行字符串扩展

如何在tcl中调用函数的上下文中执行字符串扩展,tcl,Tcl,如何在下面的脚本中实现expand(像在tcl中一样展开命令和变量),我希望将其打印出来: ' hello { $b } {tcl world} ' 这就是我想象脚本的样子: proc clever_func {script} { set script [uplevel 1 expand [list $script]] puts "'$script'" } proc isolated_client_function {} { s

如何在下面的脚本中实现
expand
(像在tcl中一样展开命令和变量),我希望将其打印出来:

'
    hello {
        $b
    }
    {tcl world}
'
这就是我想象脚本的样子:

proc clever_func {script} {
    set script [uplevel 1 expand [list $script]]
    puts "'$script'"
}

proc isolated_client_function {} {
    set a hello
    set b difficult
    set c tcl
    set d world

    clever_func {
        $a {
            $b
        }
        [list $c $d]
    }
}

isolated_client_function

一个示例并不足以替代一个规范,但似乎没有内置的TCL工具可以满足您的需求。可以在单个命令尾上执行替换(通过将
list
预先添加到命令,然后
eval
在您想要的任何级别对其执行替换),但不能对带有两个“命令”的伪脚本执行替换。(也可以使用
subst
执行字符串插值,但您可能已经知道为什么它不是您想要的:它还将扩展
$b

我认为有两种可能得到你想要的东西:

  • 使用标记化您的输入,然后在标记列表中手动执行替换,然后使用
    sugar::listToScript
    将结果转换回文本形式。
    sugar
    macroprocessor的这些功能旨在让您在保留格式、注释和布局的同时从语义上修改脚本

  • 将您的输入分解为单独的“命令”:首先在每个换行符和分号处拆分,然后使用
    info complete
    收集与完整的“命令”相对应的片段(IIRC将有一些带有反斜杠换行符的角落案例:当心)。在每一个完整的“命令”上,使用在必要的上下文(
    uplevel
    )中计算结果的方法,在“列表”前面加上前缀。因此,对于每个命令,您将得到一个列表,其中在批准时已经执行了替换。您将丢失每个“命令”中格式的细微差别(如分隔单词的空格数和空格类型),并且您将丢失原始的命令分隔符,除非您自己注意记住它们。如果目标是让一种“预扩展脚本”稍后在其他上下文中进行评估,那么这对您来说可能并不坏

  • 命令会带你走到那里的大部分路

    proc expand {script} {
        uplevel 1 [list subst $script]
    }
    
    set a hello
    set b difficult
    set c tcl
    set d world
    
    expand {
        $a {
            $b
        }
        [list $c $d]
    }
    
    输出

        hello {
            difficult
        }
        tcl world
    
        hello {
            difficult
        }
        {tcl world}
    
    我不知道如何防止
    $b
    被替换。您可能需要自己解析脚本

    如果您希望最后一部分有您演示的引用,您需要另一个级别的列表

    expand {
        $a {
            $b
        }
        [list [list $c $d]]
    }
    
    输出

        hello {
            difficult
        }
        tcl world
    
        hello {
            difficult
        }
        {tcl world}
    

    谢谢你的回答@anton kovalenko。在我的示例中,我将只使用$script变量来执行命令(而不是像我为了谈论一些事情而打印命令),因此如果有一种方法可以转换$script,以便第一个命令将在
    uplevel
    下执行,我可以分配剩余的命令(第二个、第三个等命令)回到$script,然后重复,然后我将是一个非常快乐的小兔子。我发现你链接的sugar文档页面非常难阅读。有没有更清晰的参考资料?解析是达到预期效果的唯一途径。另外两页要看的是和;我不知道哪一个更容易确定。(使用
    info complete
    只是“解析”的一种变体。)感谢您的回答。我只是认为我需要额外的引号级别,因为字符串实际上将用作脚本,在名称空间eval下执行-这意味着它将再次展开,因此我需要在Smart_func中添加额外的引号。