将 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,在评估代码时,Tcl
将 C:\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}
这也不太好(而且很容易忘记正确引用它)。
我遇到过这种情况,我必须执行 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,在评估代码时,Tcl
将 C:\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}
这也不太好(而且很容易忘记正确引用它)。