让我们说我有环境变量PO,值为1.
如果我使用LINUX echo命令,我得到:
tuple
但是,如果我使用TCL和exec,我不会得到插值:
>echo $PO
1
现在,如果我做一些更精细的事情,通过使用regsub将每个$ {varname}替换为[lindex array get env varname] 0],并使用substr,它可以工作:
>exec echo "\$PO"
$PO
我有一些角落案件,当然。但是为什么exec没有回馈shell会做什么?
答案 0 :(得分:3)
为什么exec没有回馈shell会做什么?
因为exec
不是shell。
从shell执行echo $PO
时,echo
不负责解析值。在调用$PO
之前,shell会将echo
转换为值。从shell调用它时,echo
永远不会看到$PO
。
如果你试图模仿shell的功能,那么你需要做与shell相同的工作(或者,调用一个实际的shell来为你工作)。
答案 1 :(得分:2)
Tcl是一个很多更关注它的插值位置比Unix shell通常要小心。它使环境变量不受影响,因此您不会意外地绊倒它们,并且在调用子进程时执行的处理要少得多。这完全是设计的!
尽可能(除了少数例外)Tcl将参数传递给exec
到它创建的子进程。它还具有引用字符串的标准机制,以便您可以在参数实际传递给exec
之前准确控制发生的替换。这意味着当你这样做时:
exec echo "\$PO"
Tcl将执行其正常的替换规则并获得命令调度的这些确切参数:exec
,echo
和$PO
。然后调用exec
命令,该命令使用一个参数echo
启动$PO
程序,该命令就是这样做的。 (贝壳通常首先替换该值。)如果您改为:
exec echo {$PO}
你会得到同样的效果。或者即使你做完了:
exec {*}{echo $PO}
你仍然最终将完全相同的字符输入exec
作为其参数。如果你想在它上面运行shell,你应该明确地要求它:
exec /bin/sh -c {echo $PO}
大括号中的位有一个完整的(小)shell脚本,并将进行评估。你甚至可以做到这一点:
exec /bin/sh -c {exec echo '$PO'}
这有点无用,但它有效。
您也可以从自己的代码中进行任何替换。我目前最喜欢的Tcl 8.7(开发中)是:
exec echo [regsub -all -command {\$(\w+)} "\$PO" {apply {- name} {
global env
return $env($name)
}}]
好的,这完全是过度的,但由于你可以使用任何旧的复杂RE和脚本来进行替换,它是一个主要的动力工具。 (您可以在较旧的Tcl中使用string map
,regsub
和subst
执行类似的操作,但这样做有点难度。)天空和您的想象力是唯一的限制。