Tcl 如何将puts的输出作为输入提供给proc?
我有一个将列表打印为格式化表的程序。这是一个像print_table$temp这样的用例 如果我使用“puts”命令打印输出作为proc print_表的输入,如何给出不同proc的输出 我想让下面的工作Tcl 如何将puts的输出作为输入提供给proc?,tcl,Tcl,我有一个将列表打印为格式化表的程序。这是一个像print_table$temp这样的用例 如果我使用“puts”命令打印输出作为proc print_表的输入,如何给出不同proc的输出 我想让下面的工作 > print_table [abc $list1] ============== | abc | 1 | | defg | 2 | | hijlk | 3 | | lmn | 4 | ============== 最简单的方法之一是临时替换put # P
> print_table [abc $list1]
==============
| abc | 1 |
| defg | 2 |
| hijlk | 3 |
| lmn | 4 |
==============
最简单的方法之一是临时替换
put
# Partial emulation of [puts] API; assumes we don't write to other files
proc capturing_puts {args} {
global capturedStdout
set value [lindex $args end]
set args [lrange $args 0 end-1]
if {"-nonewline" ni $args} {
append value "\n"
}
append capturedStdout $value
}
# A helper procedure to install and restore the replacement [puts] implementation
proc capture {script} {
global capturedStdout
rename puts original_puts
rename capturing_puts puts
set capturedStdout ""
try {
uplevel 1 $script
} finally {
# Restore the original, even on error!
rename puts capturing_puts
rename original_puts puts
}
return $capturedStdout
}
# Now we can use it like this
set output [capture {
abc $list1
}]
print_table $output
如果您可以使打印代码使用(可选)参数来指定要写入的通道,则更容易。然后,您根本不需要在输出捕获方面乱来
我认为可以使用通道转换来进行捕获,这比用稍微复杂的API(
put
)替换命令要简单得多,但是编写它们要复杂得多。正如Donal指出的,打印代码最好使用通道作为参数。或者,如果您无法控制所有打印过程,或者您不想触碰它们,则使用通道拦截器(如前所述):
信道拦截器被实现为信道变换;以前也有报道过
步骤1:定义通道拦截器
上面的片段是直接从中派生出来的
步骤2:在打印代码周围使用stdout
注册拦截器
您可以将拦截样板文件打包到print\u table
,使其看起来像:print\u table{abc$list1}
proc print_table {script} {
# set up interception
uplevel 1 $script
# remove interception
}
@Donal,@Calivin先生,你的两个解决方案都接近我的预期。但它将所有数据打印在一个列中 建议的代码给出如下输出:
> print_table [capture {abc $list1}]
========
| abc
| 1
| defg
| 2
| hijlk
| 3
| lmn
| 4
========
我已经输入了print_表的代码,可能是我可以添加proc print_表的详细信息,如果进行任何更改更有意义,我当前正在输入一个列表名表。本可以有更好的方法来编写这个过程
proc print_table { table } {
set col_len [llength [lindex $table 0]]
for {set i 0} {$i < $col_len} { incr i } { set col_wid($i) 0 }
foreach line $table {
for {set i 0} {$i < $col_len} { incr i } {
set temp_col_width($i) [string length [lindex $line $i]];
if { $col_wid($i) > $temp_col_width($i) } { set col_wid($i) $col_wid($i) } else { set col_wid($i) $temp_col_width($i) }
}
}
set total_col 0; for {set i 0} {$i < $col_len} { incr i } { set total_col [expr $total_col + $col_wid($i) ] } ; set total_col [expr $total_col + (($col_len-2) * 2) + 9 ];
set table_length [llength $table]; set j 0 ;
foreach line $table {
set line1 ""; set line2 "";
for {set i 0} {$i < $col_len} { incr i } {
if { $i == 0 } {
append line1 " | [format "%-$col_wid($i)s" [lindex $line $i]] "
} elseif { $i == [expr $col_len -1] } {
append line1 " | [format "%-$col_wid($i)s" [lindex $line $i]] |"
} else {
append line1 "| [format "%-$col_wid($i)s" [lindex $line $i]] "
}
}
if { $j == 0 } {
puts " [string repeat = [expr [string length $line1]-1]]";
puts "$line1";
#puts " [string repeat = [expr [string length $line1]-1]]";
} elseif { $j == 1 && $j == [expr $table_length - 1] } {
puts "$line1" ;puts " [string repeat = [expr [string length $line1]-1]]"
} elseif { $j == [expr $table_length - 1] } {
puts "$line1" ; puts " [string repeat = [expr [string length $line1]-1]]";
} else { puts "$line1" }
incr j;
}
}
proc print_table{table}{
设置列[L长度[lindex$表0]]
对于{set i 0}{$i<$colu len}{incr i}{set colu wid($i)0}
每行$table{
对于{set i 0}{$i<$colu len}{incr i}{
设置临时列宽度($i)[字符串长度[lindex$行$i];
如果{$colu-wid($i)>$temp-colu-width($i)}{set-colu-wid($i)$colu-wid($i)}其他{set-colu-wid($i)$temp-colu-width($i)}
}
}
集合总列0;对于{set i 0}{$i<$col_len}{incr i}{set total_col[expr$total_col+$col_wid($i)]};集合总列[expr$total_col+($col_len-2)*2)+9];
设置表格长度[L长度$table];设置j 0;
每行$table{
将第1行设置为“”;将第2行设置为“”;
对于{set i 0}{$i<$colu len}{incr i}{
如果{$i==0}{
追加第1行“|[格式“%-$col_wid($i)s”[lindex$行$i]]”
}elseif{$i==[expr$colu len-1]}{
追加第1行“|[格式“%-$col_wid($i)s”[lindex$行$i]]”
}否则{
追加第1行“|[格式“%-$col_wid($i)s”[lindex$行$i]]”
}
}
如果{$j==0}{
放入“[string repeat=[expr[string length$line1]-1]”;
放入“$line1”;
#放入“[string repeat=[expr[string length$line1]-1]”;
}elseif{$j==1&&$j==[expr$table_length-1]}{
放置“$line1”;放置“[string repeat=[expr[string length$line1]-1]”
}elseif{$j==[expr$table_length-1]}{
放置“$line1”;放置“[string repeat=[expr[string length$line1]-1]”;
}else{puts“$line1”}
增量j;
}
}
谢谢@DonalFellows。不确定我是否完全理解了该解决方案,但该解决方案似乎没有产生预期的输出。我只是把输出看作是abc 1 defg 2 hijlk 3 lmn 4我有很多这样的过程(比如abc示例),所以将put更改为通道输出会很乏味,所以我想使用它们生成的任何输出到格式化表中。无论您提出什么解决方案,都必须对代码进行更改。利用编辑的全局搜索“n”替换来减少繁琐的工作。@TradeCoder我写的例子令人困惑,因为我对你的问题有点误读。更新…接近所需,需要一些最终改进。。发布评论是新的,因此无法在评论中发布代码,但添加为新答案以获取详细信息
proc print_table {script} {
# set up interception
uplevel 1 $script
# remove interception
}
> print_table [capture {abc $list1}]
========
| abc
| 1
| defg
| 2
| hijlk
| 3
| lmn
| 4
========
proc print_table { table } {
set col_len [llength [lindex $table 0]]
for {set i 0} {$i < $col_len} { incr i } { set col_wid($i) 0 }
foreach line $table {
for {set i 0} {$i < $col_len} { incr i } {
set temp_col_width($i) [string length [lindex $line $i]];
if { $col_wid($i) > $temp_col_width($i) } { set col_wid($i) $col_wid($i) } else { set col_wid($i) $temp_col_width($i) }
}
}
set total_col 0; for {set i 0} {$i < $col_len} { incr i } { set total_col [expr $total_col + $col_wid($i) ] } ; set total_col [expr $total_col + (($col_len-2) * 2) + 9 ];
set table_length [llength $table]; set j 0 ;
foreach line $table {
set line1 ""; set line2 "";
for {set i 0} {$i < $col_len} { incr i } {
if { $i == 0 } {
append line1 " | [format "%-$col_wid($i)s" [lindex $line $i]] "
} elseif { $i == [expr $col_len -1] } {
append line1 " | [format "%-$col_wid($i)s" [lindex $line $i]] |"
} else {
append line1 "| [format "%-$col_wid($i)s" [lindex $line $i]] "
}
}
if { $j == 0 } {
puts " [string repeat = [expr [string length $line1]-1]]";
puts "$line1";
#puts " [string repeat = [expr [string length $line1]-1]]";
} elseif { $j == 1 && $j == [expr $table_length - 1] } {
puts "$line1" ;puts " [string repeat = [expr [string length $line1]-1]]"
} elseif { $j == [expr $table_length - 1] } {
puts "$line1" ; puts " [string repeat = [expr [string length $line1]-1]]";
} else { puts "$line1" }
incr j;
}
}