如何限制tclsh命令行的标准输出



在tclsh命令行以交互方式运行命令时,有没有办法截断返回值打印到stdout的部分?

例如,这将花费很长时间,因为返回值将打印到stdout。

tclsh> set a [lrepeat 500000000 x]

我知道我可以在同一行中添加一个伪命令,但这是一个临时解决方案。我可以在~/.tclshrc中设置一些将stdout截断为有限长度的内容吗?

tclsh> set a [lrepeat 500000000 x] ; puts ""

也许这是一个XY问题(因为关闭或吞咽stdout的打印似乎可以满足OP(,但实际问题是:

我是否可以在~/.tclshrc中设置一些内容,将stdout截断为有限长度?

您可以在stdout(和/或stderr(上使用拦截器将字符串限制为默认限制:

oo::class create capped {
variable max
constructor {m} {
set max $m
} 
method initialize {handle mode} {
if {$mode ne "write"} {error "can't handle reading"}
return {finalize initialize write}
}
method finalize {handle} {
# NOOP
}

method write {handle bytes} {
if {[string length $bytes] > $max} {
set enc [encoding system]
set str [encoding convertfrom $enc $bytes]
set newStr [string range $str 0 $max-1]
if {[string index $str end] eq "n"} {
append newStr "n"
}
set bytes [encoding convertto $enc $newStr]
}
return $bytes
}
}

使用chan pushchan pop,您可以打开/关闭上限,例如30个字符:

% chan push stdout [capped new 30]
serial1
% puts [string repeat € 35]
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
% chan pop stdout
% puts [string repeat € 35]
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€

一些备注:

  • 您可以使用一个对象、一个名称空间或一个进程来提供所需的通道拦截器接口(initialize、write…(;我更喜欢实物。

  • Adwrite:您希望根据基于字符的限制进行上限设置,而不是字节级别的限制。然而,write接收的是一个字节串,而不是一个字符串。因此,在强制执行限制时需要小心(使用encoding convertfromencoding convertto将字节字符串反向转换为char字符串,反之亦然(。

  • 类似地,max的某些值可能不是一个好的选择,还是应该限制值的范围。例如,1或0的max将有效地关闭基本REPL(提示%(。

  • 至于tclshrc:您可能希望在其中放置拦截器定义和chan push调用,以启用默认情况下的封顶?

tclsh是一个REPL;P〃;这就是你所看到的。如果不深入了解来源,我不知道有什么简单的方法可以完全实现你的要求。

如果我记得这样做,list命令对于提供无输出非常有用

set a [lrepeat 500000000 x]; list

或者可能是一些有信息的

set a [lrepeat 500000000 x]; llength $a

如果你想获得程序:

proc i {val} {set ::tcl_interactive $val}

然后执行i offi 0i false以关闭交互,然后执行结果较大的命令。非交互式会使命令结果的打印静音,但也会关闭提示,这可能会令人困惑。恢复与i oni 1i true的交互

最新更新