将 eval exec 与路径中包含空格的可执行文件名称一起使用

Using eval exec with an executable name containing spaces in the path

我遇到过这种情况,我必须执行 tshark 来解码 pcap 文件。

tshark 的位置是 C:\Program Files\Wireshark\tshark.exe

% set fileName TestTShark.pcap
TestTShark.pcap
% set sTsharkCmd "-r $fileName  -Tfields -e ip.src"
-r TestTShark.pcap  -Tfields -e ip.src
% set tsharkPath "C:/Program Files/Wireshark/tshark.exe"
C:/Program Files/Wireshark/tshark.exe
% eval exec $tsharkPath $sTsharkCmd > packet.log
couldn't execute "C:\Program": no such file or directory
% exec $tsharkPath $sTsharkCmd > packet.log
tshark: The file " TestTShark.pcap  -Tfields -e ip.src" doesn't exist.
% set tsharkPath "C:\Program Files\Wireshark\tshark.exe"
C:\Program Files\Wireshark\tshark.exe
% exec $tsharkPath $sTsharkCmd > packet.log
tshark: The file " TestTShark.pcap  -Tfields -e ip.src" doesn't exist.
% eval exec $tsharkPath $sTsharkCmd > packet.log
couldn't execute "C:Program": no such file or directory

由于路径包含 space,在评估代码时,TclC:\Program 视为程序名称并抛出错误。然后我设法用反斜杠转义了 space ,如下所示,然后就起作用了。

%  set tsharkPath "C:/Program\ Files/Wireshark/tshark.exe"
C:/Program\ Files/Wireshark/tshark.exe
% eval exec $tsharkPath $sTsharkCmd > packet.log
% type packet.log
20.0.0.5
%

我只是好奇。还有其他选择可以处理这种情况吗? {*} 也观察到同样的问题。

eval [list exec $tsharkPath {*}$sTsharkCmd]

创建新命令以 sTsharkCmd 属性分隔...

您的问题是您希望 space 成为从变量中获取的参数的一部分,但要将来自另一个参数的参数分开。默认情况下,Tcl 将尝试将相同的统一规则应用于 所有 参数:您需要做一些额外的事情来改变它。

您想使用参数的扩展您的命令

% eval exec $tsharkPath $sTsharkCmd > packet.log

应该写成:

% exec $tsharkPath {*}$sTsharkCmd > packet.log

看看它是如何变短的?它也更安全。尽量避免 eval 除非你真的在做一些非常复杂的事情。 (我的代码中几乎不需要它……)


如果您受困于没有 {*} 的旧版 Tcl,您需要改为这样做:

% eval [linsert $sTsharkCmd 0 exec $tsharkPath > packet.log]

哪个非常不明显,或者这个:

% eval {exec $tsharkPath} $sTsharkCmd {> packet.log}

这也不太好(而且很容易忘记正确引用它)。