我正在维护一些旧代码并发现以下内容......
if {[catch {exec -- echo $html_email > $file} ret]} {
puts $ret
return 0
}
...由于HTML电子邮件的第一个字符为<
,即
couldn't read file "html>
<title>cama_Investigate 00000560554PONY1</title>
<style type="text/css">
...
...
...
被解释为I / O重定向运算符。以前这不是问题因为我们用一些标题开始发送电子邮件,例如
append html_email "Content-Type : text/html; charset=us-ascii\n"
append html_email "Content-Disposition: inline\n"
我将重写所有这些以使用Tcl的本机文件I / O,因此这个问题主要是学术性的:当传递给{{1}时,保护变量内容不被shell解释的正确方法是什么? }?
我正在使用Tcl 8.0.5和csh,但如果可能的话,我对一般答案感兴趣。
答案 0 :(得分:2)
Tcl&#39; exec
很时髦,唉。它坚持解释以<
字符作为重定向开头的参数。 (还有一些其他的,但你不太可能击中它们。)除了将数据写入临时文件并从中重定向之外,没有一般的解决方法。
set ctr 0
while 1 {
set filename /tmp/[pid].[incr ctr].txt
# POSIX-style flags; write-only, must create or generate error
if {[catch {open $filename {WRONLY CREAT EXCL}} f] == 0} break
}
puts $f $html_email
close $f
exec echo <$filename >$file
file delete $filename
这非常复杂!通过改变我们使用的程序,我们可以做得更好。如果我们使用echo
而不是cat
,我们可以使用exec
的heredoc语法:
exec cat <<$html_email >$file
因为在这种情况下,字符直接通过管道传递(这是Tcl如何做到这一点),所以不会出错。然而它仍然仍然愚蠢,因为Tcl完全能够直接写入文件,更便携,并且开销更少:
set f [open $file "w"]
puts $f $html_email
close $f
是的,这实际上是上面第一个示例的一般替换非常简化的版本。让我们做一些更加明显正确的简单事情,因为那时未来会有更少的惊喜。
答案 1 :(得分:0)
您可以间接调用目标命令,通过shell路由它:
exec -- csh -c "echo '$html_email'" > $file
或
exec -- csh -c "exec echo '$html_email'" > $file