【问题标题】:TCL/Expect - exec - how to execute program with parametersTCL/Expect - exec - 如何执行带参数的程序
【发布时间】:2015-03-21 15:51:30
【问题描述】:

我正在tclsh 中尝试使用 TCL 命令exec,这是我的结果:

% set show_me_dir "ls"
ls
% exec $show_me_dir
VboxSharedFolder
% set show_me_dir "ls -la"
ls -la
% exec $show_me_dir
couldn't execute "ls -la": no such file or directory
% set show_me_dir {ls -la}
ls -la
% exec $show_me_dir
couldn't execute "ls -la": no such file or directory
% ls -la
total 141
d---------+ 1 wakatana Domain Users     0 Jan 22 19:12 .
d---------+ 1 wakatana Domain Users     0 Apr 16  2014 ..
----------+ 1 wakatana Domain Users 20214 Jan 23 18:43 .bash_history
----------+ 1 wakatana Domain Users  1494 Apr 15  2014 .bash_profile
----------+ 1 wakatana Domain Users  7593 Jan 22 19:03 .bashrc
d---------+ 1 wakatana Domain Users     0 Jan 15 14:56 VboxSharedFolder
%

谁能解释我如何执行带参数的命令?

编辑:

Expanding a list of parameters in Tcl and eval 文章中的以下示例让我们大开眼界:

变量$action 仅扩展为字符串"piemiddle apple" AFTER 命令行已拆分为各个参数:

% set action {piemiddle apple}
% set $action
can't read "piemiddle apple": no such variable

结果:set 命令“看到”一个参数,相当于:

% set {piemiddle apple}

扩展运算符允许您指定要扩展的变量命令行被拆分为单独的参数:

% set action {piemiddle apple}
% set {*}$action
apple

结果:set 命令“看到”两个参数,相当于:

% set piemiddle apple

在早期版本的 Tcl 中,eval 命令是推荐的替代方法,并且今天仍然可用。

% set action {piemiddle apple}
% eval set $action
apple

另一个证明扩展运算符功能的例子:

% set {*}"name Linus"
Linus
% puts $name
Linus
%
%
% set distro Unbuntu
Unbuntu
% set {*}"linux $distro"
Unbuntu
% puts $linux
Unbuntu
%
%

最后发现exec 需要命令作为它的第一个参数和第一个命令选项作为它的第二个参数等等。

% exec "ls" "-la"
total 137
d---------+ 1 wakatana Domain Users     0 Jan 22 19:12 .
d---------+ 1 wakatana Domain Users     0 Apr 16  2014 ..
----------+ 1 wakatana Domain Users 20214 Jan 23 18:43 .bash_history
----------+ 1 wakatana Domain Users  1494 Apr 15  2014 .bash_profile
----------+ 1 wakatana Domain Users  7593 Jan 22 19:03 .bashrc
d---------+ 1 wakatana Domain Users     0 Jan 15 14:56 VboxSharedFolder
%
%
% exec "ls -la"
couldn't execute "ls -la": no such file or directory

【问题讨论】:

  • 请花点时间思考一下论据扩展的主题,这在您上一个问题的答案中已向您解释过。

标签: arguments tcl exec command-line-arguments expect


【解决方案1】:

exec 构建命令的最安全方法是使用Tcl 的list。例如:

% set tcl_version
8.5
% set cmd [list ls -l tmp]
ls -l tmp
% eval exec $cmd
total 32
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 file.txt
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-1.dat
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-2.dat
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-3.dat
% exec {*}$cmd
total 32
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 file.txt
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-1.dat
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-2.dat
-rw-r--r--  1 pynexj  staff  1176 Jan 23 23:24 foo-3.dat
%

请注意,{*} 是 Tcl 8.5 的新语法,有助于减少 eval 的使用。

【讨论】:

  • TCL列表不就是普通的字符串,每个单词用空格隔开吗?我认为set cmd [list ls -la /tmp]set cmd "ls -la /tmp" 是一样的。
  • 请注意,8.4 现在不支持了。我们将不再为它做安全补丁。并不是说我们知道其中有任何需要 补丁,无论如何只要转到 8.5 就不会更好地修复这些补丁。两者之间的兼容性级别大多非常高(除非您依赖整数是固定宽度,在这种情况下您的代码已经不可移植)。
  • @WakanTanka:不一样。例如,想想如何在不使用list 的情况下做与set cmd [list ls -l "foo bar.txt"] 相同的事情。还有set cmd [list echo \[]?
  • @whjm:例如通过使用反斜杠转义?这是一个有点难看的语法,但我想它会起作用。
  • 是的,通过使用反斜杠转义,我们可以构造有效的列表。但这并不总是那么容易,而且容易出错。
【解决方案2】:

作为ls 命令的示例,您可以执行以下操作:

exec {*}ls -lsa {*}[glob *.cpp]

请看What does {*} do in TCL?

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 2012-11-08
    • 1970-01-01
    • 2014-06-17
    • 2018-10-16
    • 1970-01-01
    • 2014-06-18
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多