TCL - 将STDIN喂给执行官

时间:2016-06-24 15:17:30

标签: tcl exec stdin

我正在尝试使用TCL执行外部程序时实现重试机制。尝试将STDIN提供给外部程序时,我遇到了一些问题。我现在正在尝试一个简化的例子试图解决这个问题。使用以下python脚本(simple.py):

x = raw_input()
y = raw_input()
print x + y

从输出中输入2个字符串将是字符串的串联结果。

现在,以下命令在TCL解释器中起作用:

% exec python stuff.py << 1\n2
12

但是,当我尝试在单独的命令中拆分它,或者在执行此操作之前将它们添加到字符串中时,它会失败。

失败1:

% set cmd "python simple.py << 1\n2"
% exec $cmd
couldn't execute "python simple.py << 1
2": no such file or directory

失败2:

% set cmd1 "python simple.py"
% set cmd2 "1\n2"
% exec $cmd1 << $cmd2

无法执行“python simple.py”:没有这样的文件或目录

失败3:

% set fullCommandString "exec python simple.py << 1\n2"
% eval $fullCommandString
Traceback (most recent call last):
  File "simple.py", line 2, in <module>
    y = raw_input()
EOFError: EOF when reading a line

第三种情况似乎启动了脚本,但它将两行STDIN解释为一行。

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

默认情况下,Tcl的命令不会在其参数中重新解释空格。 exec是其中之一,它遵循相同的规则。这意味着您需要告诉Tcl将单词列表解释为单词列表,否则它只是一个字符串。幸运的是,{*}就是这样;扩展运算符语法将单词的其余部分解释为Tcl列表,并在您编写它的位置使用该列表中的单词。我发现它非常有用。

最简单的解决方法实际上是你的第二种情况:

% set cmd1 "python simple.py"
% set cmd2 "1\n2"
% exec {*}$cmd1 << $cmd2

您可以通过添加Tcl列表引用来修复第一个和第三个,以确保1\n2仍被解释为单个单词(否则换行是一个非常合理的列表项分隔符)。

% set cmd "python simple.py << {1\n2}"
% exec $cmd
% set fullCommandString "exec python simple.py << {1\n2}"
% eval $fullCommandString

第三部分可以写得更经济:

% set fullCommandString "exec python simple.py << {1\n2}"
% {*}$fullCommandString

根据经验,如果您在现代Tcl中看到eval(注意:不是 namespace evalinterp evaluplevel,那么它通常表明,通过谨慎使用扩展,可以提高某些代码的效率并减少错误。

tl; dr:在第二个示例中将{*}放在$cmd1之前,以获得惯用的修复。