我在TCL中比较新,在TCL提示符下,当我们调用带有一些返回值的proc时,proc的返回值由tcl回显。有没有办法阻止它(不影响看跌期权或类似功能)作为例子
bash$ tclsh
% proc a {} { puts "hello"; return 34; }
% a
hello
34
%
现在我如何抑制34进入屏幕?任何帮助表示赞赏。
更新: 实际上proc是另一个工具的一部分,之前它没有任何返回值,但现在有条件地它可以返回一个值。 它可以从脚本中调用,不会有任何问题(正如布莱恩指出的那样)。它可以从交互式提示中调用,然后在所有必要的输出之后,返回值被不必要地打印出来。 所以1)我没有改变用户的tclshrc的工具2)现有的脚本应该继续工作。 并且看起来奇怪的是每次调用proc时,在所有必要的输出之后,都会打印一个数字。对于用户来说,这是一个不必要的信息,除非他已经抓住了价值并想要做某事。所以我希望将价值交付给用户,但不要打印到提示/ UI(希望我很清楚)
答案 0 :(得分:2)
tclsh
和wish
中的交互式shell代码将打印任何非空结果。为了不打印任何内容,您必须让“line”上的最后一个命令产生一个空结果。但是使用哪个命令?
许多命令会产生空结果:
if 1 {}
subst ""
format ""
然而,最短的可能是:
list
因此,您可以编写代码,如:
a;list
当然,只有当您的命令实际产生一个您不想看到的大结果时,这才真正有用。在这些情况下,我经常发现使用衡量结果大小的东西是最有用的,例如:
set tmp [something_which_produces a_gigantic result]; string length $tmp
我找到的最有用的命令是string length
,llength
和dict size
。
如果绝对必须不打印命令的结果,则必须编写自己的交互式循环。有两种方法可以执行此操作,具体取决于您是否在事件循环内运行:
这个简单的版本只是检查命令名是否在用户键入的内容中。否则,任意抛弃结果可能不是一个好主意!
set accum ""
while {[gets stdin line] >= 0} {
append accum $line "\n"
if {[info complete $accum]} {
if {[catch $accum msg]} {
puts stderr $msg
} elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
puts $msg
}
set accum ""
}
}
这只是处理阻塞IO的情况;当输入来自熟食终端时(即默认值),这是正确的事情
fileevent stdin readable handleInput
set accum ""
proc handleInput {} {
global accum
if {[gets stdin line] < 0} {
exit; # Or whatever
}
append accum $line "\n"
if {[info complete $accum]} {
if {[catch {uplevel "#0" $accum} msg]} {
puts stderr $msg
} elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
puts $msg
}
set accum ""
}
}
vwait forever; # Assuming you're not in wish or have some other event loop...
上面的代码使用![string match *TheSpecialCommand* $accum]
来决定是否丢弃命令结果,但这非常难看。利用Tcl自带的内置钩子的更优雅的方法是使用execution trace来检测命令是否已被调用(为简洁起见,我将在此处仅显示非事件循环版本)。这样做的另一个好处是可以很容易地扩展以抑制多个命令的输出:只需将跟踪添加到每个命令。
trace add execution TheSpecialCommand enter SuppressOutput
proc SuppressOutput args {
# Important; do not suppress when it is called inside another command
if {[info level] == 1} {
set ::SuppressTheOutput 1
}
}
# Mostly very similar from here on
set accum ""
while {[gets stdin line] >= 0} {
append accum $line "\n"
if {[info complete $accum]} {
set SuppressTheOutput 0; # <<<<<< Note this!
if {[catch $accum msg]} {
puts stderr $msg
} elseif {$msg ne "" && !$SuppressTheOutput} { # <<<<<< Note this!
puts $msg
}
set accum ""
}
}
要清楚,我不会永远在我自己的代码中执行此操作!如果重要的话,我只是手动抑制输出。
答案 1 :(得分:1)
您可以在.tclshrc ...
中创建一个空过程proc void {} {}
...当您不需要返回值时,请使用;void
结束该行。
答案 2 :(得分:-1)
使用 tcl_interactive 变量来启用值的返回,虽然我不确定这在哪里有用...
proc a {} {
puts "hello"
if { [info exist tcl_interactive] } {
return {};
} else {
return 34;
}
}