1

如何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
4

2 回答 2

2

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

我看到两种可能性来获得你想要的东西:

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

  2. 将您的输入分解为单独的“命令”:首先在每个换行符和分号处拆分,然后用于info complete收集与完整“命令”相对应的部分(IIRC 会有一些带有反斜杠换行符延续的极端情况:当心)。在每个完整的“命令”上使用前置的技巧,"list "在必要的上下文 ( uplevel) 中评估结果。因此,对于每个命令,您将获得一个列表,其中在适当的时候已经执行了替换。您将丢失每个“命令”内部格式的细微差别(例如分隔单词的空格数和空格类型),并且您将丢失原始命令分隔符,除非您自己注意记住它们。如果目标是获得一种“eval稍后在其他一些情况下使用。

于 2013-02-09T20:39:54.140 回答
1

subst命令将带你去那里的大部分地方。

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

我不确定如何防止$b被替换。您可能必须自己解析脚本。

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

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

输出

    hello {
        difficult
    }
    {tcl world}
于 2013-02-10T01:39:54.580 回答