tcl:eval 和 exec 混淆点

tcl: eval and exec confusing point

我对 Tcl 中的 execeval 有点困惑。在以下示例中:

set cmd "mkdir new_folder";
exec $cmd

无法使用错误消息:couldn't execute "mkdir new_folder" no such file or directory. eval 有效

set cmd "mkdir new_folder";
eval exec $cmd

我也试过这种方法:

set cmd_1 "mkdir";
set cmd_2 "new_folder"
exec $cmd_1 $cmd_2

它也很好用。 那是什么原因呢?

由于您自己的评论中已经暗示,问题在于参数的解释。如果您仍然希望在单个字符串中使用命令,您可以使用扩展运算符 {*}.

set cmd "mkdir new_folder"
exec {*}$cmd ;# Tcl 8.5 or higher
eval exec $cmd ;# alternative solution

这不仅适用于 exec 命令。一般规则是:如果一个命令接受多个参数,并说存储在变量 params 中,当您调用该命令时,必须扩展参数: cmd {*}$params。 因此,以下这些脚本是等价的

cmd param1 param2

set params "param1 param2"
cmd {*}$params

您真正需要注意的地方是您的参数之一是否包含空格。那样的话,eval就不知道怎么办了:

% set cmd "mkdir 'dir with spaces'"
mkdir 'dir with spaces'
% eval exec $cmd
% exec ls -l
total 20
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 'dir
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 spaces'
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 with

你真正想做的是使用列表。然后 Tcl 准确地理解了单独的元素是什么

% set cmd [list mkdir "dir with spaces"]
mkdir {dir with spaces}
% exec {*}$cmd
% exec ls -l
total 24
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 'dir
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:53 dir with spaces
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 spaces'
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 with

我看到这个 post 是旧的,我只是在我的朋友问到这个问题时把我的答案放在里面。 所以想象一下你只是在 bash shell 中执行命令并想要创建一个目录。在这种情况下,你会 运行:

  • mkdir new_folder

但是现在想像一下如果您 运行 使用如下相同的命令会发生什么:

  • "mkdir new_folder"

当然如果会抛出一个错误说:

bash: mkdir new_folder: command not found

现在它与 TCL exec 命令相同,当您将所有内容作为单个参数传递给 exec 时,它以相同的方式传递给 bash:

  • exec "mkdir new_filder" # 实际执行:
  • "mkdir new_folder" # 在 bash 中然后 hense 会抛出一个错误

现在为什么 eval 有用?只是因为它在 TCL 中评估后删除了范围,而你实际上执行了:exec mkdir new_folder

希望对您有所帮助!