在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 push
和chan pop
,您可以打开/关闭上限,例如30个字符:
% chan push stdout [capped new 30]
serial1
% puts [string repeat € 35]
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
% chan pop stdout
% puts [string repeat € 35]
€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
一些备注:
您可以使用一个对象、一个名称空间或一个进程来提供所需的通道拦截器接口(initialize、write…(;我更喜欢实物。
Ad
write
:您希望根据基于字符的限制进行上限设置,而不是字节级别的限制。然而,write
接收的是一个字节串,而不是一个字符串。因此,在强制执行限制时需要小心(使用encoding convertfrom
和encoding 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 off
或i 0
或i false
以关闭交互,然后执行结果较大的命令。非交互式会使命令结果的打印静音,但也会关闭提示,这可能会令人困惑。恢复与i on
或i 1
或i true
的交互