如何在tcl中以统一的方式显示输出

如何在tcl中以统一的方式显示输出,tcl,Tcl,我对格式命令有疑问。我的输出是一种集群和非均匀的,如下所示 24-04-2011 16:07 <DIR> Administrator 15-05-2011 16:05 <DIR> confuser 01-02-2011 20:57 <DIR> Public 输出am receiving是根据第一个字符串中的字母数,例如administrator confuser public techm。因此,我需要知道的是如

我对
格式
命令有疑问。我的输出是一种集群和非均匀的,如下所示

    24-04-2011    16:07  <DIR>  Administrator 
    15-05-2011 16:05 <DIR> confuser 
    01-02-2011   20:57  <DIR>  Public 

输出am receiving是根据第一个字符串中的字母数,例如administrator confuser public techm。因此,我需要知道的是如何获得不考虑第一个字符串长度的输出,并给出适当的统一列输出。

您必须首先收集要显示的所有记录,然后找到要放置在第一个输出列中的最长字符串的大小;让我们称之为
max\u len
。然后,知道了这个大小,您就在第一列中的每个要输出的字符串的右边(即在字符串的末尾)填充了那么多空格字符,以使生成的总长度正好是
max_len
(提示:使用
string repeat”“[expr{$max_len-[string length$s]
来构造填充块)然后使用该填充输出字符串

顺便说一下,您可以看到
parray
标准命令是如何实现的,因为它正是您想要的。要查看其实现,请执行

set x {Administrator foo Molly bar Dolly blorb}
parray x
info body parray

在交互式Tcl shell提示符中(建议这样做)。

廉价的破解方法是使用制表符作为输出字符串中的分隔符(“
\t
”而不是“
”)。这将适用于少量变化,但不会处理较大的变化(或当前终端/编辑器选项卡宽度周围的小变化)

为了正确地完成这项工作,您需要首先获得要打印的所有概念行的列表(即数据,但尚未格式化)。然后遍历每一行,计算出每个字段所需的宽度,取整个数据集的最大值。这样,您就可以为
格式
配置格式字符串。下面是一个示例(对于Tcl 8.5),其中所有内容都被格式化为字符串:

proc printColumnarLines {lines} {
    foreach fields $lines {
        set column 0
        foreach field $fields {
            set w [string length $field]
            if {![info exist width($column)] || $width($column) < $w} {
                set width($column) $w
            }
            incr column
        }
    }
    foreach fields $lines {
        set column 0
        foreach field $fields {
            puts -nonewline [format "%-*s " $width($column) $field]
            incr column
        }
        puts ""; # Just the newline please
    }
}
proc printColumnarLines{lines}{
foreach字段$行{
设置列0
foreach字段$fields{
设置w[字符串长度$field]
如果{![info exist width($column)]| |$width($column)<$w}{
设置宽度($column)$w
}
增量列
}
}
foreach字段$行{
设置列0
foreach字段$fields{
puts-nonewline[格式“%-*s”$width($column)$field]
增量列
}
请把“;#换成新行
}
}
该位置格式字符串中的
*
表示采用另一个参数,指定该字段的宽度。我并不奇怪你错过了它;格式字符串实际上是一种非常密集的微语言,很容易跳过重要的一点。(其他所有使用它们的语言也是如此;很少有人知道你能用它们做什么。)


您可以使用固定的字段集做更智能的事情,其他
%
-序列也支持
*
。请注意,我通常必须进行实验才能得到我想要的(特别是浮点数…

解决此问题的最简单方法是使用struct::matrix包,它是tcllib的一部分:

package require struct::matrix

set lines {
    {Administrator 15-05-2011 16:05}
    {confuser 01-02-2011 20:57}
    {Public 29-01-2011 19:28}
    {TechM 30-04-2011 09:47}
    {"Name with space" 29-04-2011 11:05}
}

struct::matrix m; # Create a new matrix
m add columns 3; # The matrix has 3 columns: file name, date, and time
foreach line $lines {
    m add row $line; # Add a line to the matrix
}
m format 2chan; # Prints it out
输出:

Administrator   15-05-2011 16:05
confuser        01-02-2011 20:57
Public          29-01-2011 19:28
TechM           30-04-2011 09:47
Name with space 29-04-2011 11:05
注:

  • 如果某个字段包含空格,则该字段应使用双引号引起来(请参见带空格的名称)
  • format 2chan命令仅将格式字段左对齐。如果您正在查看居中或右对齐,请查看报告包

  • 使用tcl命令格式()。是的,我使用这个命令将[format{%-s%-4s%-8s}$user\t$date\t$time]输出给我,比如:Administrator 15-05-2011 16:05 confuser 01-02-2011 20:57 Public 29-01-2011 19:28 TechM
    Administrator   15-05-2011 16:05
    confuser        01-02-2011 20:57
    Public          29-01-2011 19:28
    TechM           30-04-2011 09:47
    Name with space 29-04-2011 11:05