tcl 文本处理 - 根据用户定义的值重新排列行和列中的值 [英] tcl text processing - rearrange values in rows and columns based on user defined value
问题描述
我是 tcl 的新手,想在一个简单案例的文本处理中使用它.以下格式是用于芯片设计的 Liberty(.lib 文件).对此我真的很感激.
I am new to tcl and would like to use it in text processing of a simple case. The following format is in Liberty (.lib file) which is used in chip design. I would be truly indebted for any help on this.
这是我的文件的片段(仅对值"进行文本处理)
Here is a snippet of my file (text processing to be done only on the "values")
timing () {
related_pin : "clk";
timing_type : setup_rising;
rise_constraint (constraint_template_5X5) {
index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");
index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");
index_3 ("0.084, 0.84, 3.36, 8.4, 13.44") ;
values ( \
"1.1, 1.2, 1.3, 1.4, 1.5", \
"2.1, 2.2, 2.3, 2.4, 2.5", \
"3.1, 3.2, 3.3, 3.4, 3.5", \
"4.1, 4.2, 4.3, 4.4, 4.5", \
"5.1, 5.2, 5.3, 5.4, 5.5", \
"6.1, 6.2, 6.3, 6.4, 6.5", \
"7.1 ,7.2, 7.3, 7.4, 7.5", \
"8.1, 8.2, 8.3, 8.4, 8.5", \
"9.1, 9.2, 9.3, 9.4, 9.5", \
"10.1,10.2,10.3,10.4,10.5", \
"11.1,11.2,11.3,11.4,11.5", \
"12.1,12.2,12.3,12.4,12.5", \
"13.1,13.2,13.3,13.4,13.5", \
"14.1,14.2,14.3,14.4,14.5", \
"15.1,15.2,15.3,15.4,15.5", \
"16.1,16.2,16.3,16.4,16.5", \
"17.1,17.2,17.3,17.4,17.5", \
"18.1,18.2,18.3,18.4,18.5", \
"19.1,19.2,19.3,19.4,19.5", \
"20.1,20.2,20.3,20.4,20.5", \
"21.1,21.2,21.3,21.4,21.5", \
"22.1,22.2,22.3,22.4,22.5", \
"23.1,23.2,23.3,23.4,23.5", \
"24.1,24.2,24.3,24.4,24.5", \
"25.1,25.2,25.3,25.4,25.5", \
);
}
所以所有值"都是 25 行 x 5 列查找表格式,我希望将其更改为 5 行 x 5 列表格式.为此,我想在映射完成之前询问用户他/她想要 index_3 中的 5 个值中的哪一个(同时删除 index_3 行):
So all the "values" are in a 25 rows x 5 columns lookup table format which I wish to change to a 5 rows x 5 columns table format. To accomplish this, I would like to ask the user which of the 5 values in index_3 he/she wants before mapping is done as follows (while also removing the index_3 line):
C 是基于 index_3 的用户定义列:(0.084 的第 1 列,0.84 的第 2 列,3.36 的第 3 列,8.4 的第 4 列,13.44 的第 5 列).*用户只能选择1个值
C is the user defined column based on index_3: (column 1 for 0.084, column 2 for 0.84, column 3 for 3.36, column 4 for 8.4, column 5 for 13.44). *Only 1 value can be chosen by user
映射方案:
1,C -> row 1 column 1
2,C -> row 2 column 1
3,C -> row 3 column 1
4,C -> row 4 column 1
5,C -> row 5 column 1
6,C -> row 1 column 2
7,C -> row 2 column 2
8,C -> row 3 column 2
等等..
例如,假设用户选择第 1 列(来自 index_3 的值 0.084)--> '选择''values' 中数据的整个第一列进行文本处理/排列
For EXAMPLE, say a user chooses column 1 (value 0.084 from index_3) --> which 'chooses' entire 1st column of the data in 'values' to be text processed/arranged
因此,tcl 基于映射方案完成的文本处理结果应该是:
Hence, resulting text processing done by tcl based on the mapping scheme should be:
index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");
index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");
values ( \
"1.1, 6.1, 11.1, 16.1, 21.1", \
"2.1, 7.1, 12.1, 17.1, 22.1", \
"3.1, 8.1, 13.1, 18.1, 23.1", \
"4.1, 9.1, 14.1, 19.1, 24.1", \
"5.1, 10.1,15.1, 20.1, 25.1", \
);
我的策略是这样的:
搜索rise_constraint"到零,在整个文件中文本处理哪些值
search for "rise_constraint" to zero in on which values to text process in the entire file
注释掉index_3 (...)"行;重印处理后的文件行首和行尾添加/*和*/(可选)
comment out line "index_3 (...)"; add /* and */ at beginning and end of line in reprinted processed file (optional)
根据所选的 Index_3 值(用户定义的列选择")将值"从 25 行 x 5 列表转换为 5 行 x 5 列表
convert 'values' from 25 rows x 5 columns table to 5 rows x 5 columns table BASED on Index_3 value chosen ("user defined column choice")
按原样重新打印其他行(包括处理过的文本值")
re-print other lines as is (including the text processed 'values')
我尽力解释我的编码请求.你们中的任何人都可以帮我想出在 tcl 中我可以做这样的文本处理的正确方法吗?非常感谢!!
I tried my very best to explain my coding request. Can any of you meastros please help me think of a proper way in tcl I can do such text processing? Many thanks!!
推荐答案
我终于对这个真正感兴趣了,并根据我更好的判断编写了一个完整的答案.我不会以任何方式记录它.阅读它,阅读文档,了解您不理解的命令,然后来提问.
I finally got really interested in this, and against my better judgement coded up a complete answer. I'm not going to document it in any way. Read it, read the docs for commands you don't understand, then come and ask questions.
查看您的自由文件,我发现它非常接近原生 Tcl 语法.所以你可以创建一些名为timing"、rise_constraint"等的程序,基本上就可以作为脚本运行了.
Looking at your liberty file, I see it's very close to native Tcl syntax. So you can create a few procedures named "timing", "rise_constraint", etc, and you can basically run it as a script.
package require struct::list
######################################################################
proc main {libfile} {
global lines idx3 vals
set lines [list]
set idx3 [list]
set vals [list]
evaluate_liberty $libfile
set idx [get_choice "select an index_3 value: " $idx3]
set column [struct::list mapfor elem $vals {lindex $elem $idx}]
set newvalues [list]
for {set i 0} {$i < 5} {incr i} {
lappend newvalues [lrange $column [expr {5*$i}] [expr {5*($i+1)-1}]]
}
print_liberty $newvalues
}
######################################################################
proc evaluate_liberty {libfile} {
set fh [open $libfile r]
# handle known syntax error in liberty file
set contents [string map {\", \"} [read -nonewline $fh]]
regsub -all -line {\s+$} $contents {} contents
close $fh
uplevel #0 $contents
}
proc get_choice {prompt values} {
while {1} {
for {set i 0} {$i < [llength $values]} {incr i} {
puts stderr [format "%2d. %s" $i [lindex $values $i]]
}
puts -nonewline stderr $prompt
gets stdin answer
if {[string is integer -strict $answer]} {
if {0 <= $answer && $answer < [llength $values]} {
return $answer
}
}
}
}
proc print_liberty {newvalues} {
global lines close_braces
puts [join $lines \n]
puts "values ( \\"
foreach elem $newvalues {
puts [format "\"%s\", \\" [join $elem {, }]]
}
puts ");"
for {set i 1} {$i <= $close_braces} {incr i} {
puts [format %c 125]
}
}
######################################################################
# define DSL
proc timing {label script} {
lappend ::lines [format "timing %s %c" $label 123]
incr ::close_braces
uplevel 1 $script
}
proc rise_constraint {label script} {
lappend ::lines [format "rise_constraint %s %c" $label 123]
incr ::close_braces
uplevel 1 $script
}
proc index_3 {args} {
global idx3
foreach item $args {
lappend idx3 [string map {( "" \" "" , "" ) ""} $item]
}
}
proc values {args} {
global vals
foreach set [lrange $args 1 end-1] {
lappend vals [split [regsub -all {\s*,\s*} $set { }]]
}
}
rename unknown system_unknown
proc unknown args {
lappend ::lines "[join $args];"
}
######################################################################
if {$argc == 0} {
puts "usage: $argv0 filename.lib"
exit
}
set libfile [lindex $argv 0]
if {![file exists $libfile]} {
error "no such file: $libfile"
}
main $libfile
运行:
$ tclsh liberty.tcl test.lib > newlib.lib
0. 0.084
1. 0.84
2. 3.36
3. 8.4
4. 13.44
select an index_3 value: 0
$ cat newlib.lib
timing () {
related_pin : clk;
timing_type : setup_rising;
rise_constraint (constraint_template_5X5) {
index_1 ("0.01, 0.05, 0.12, 0.2, 0.4");
index_2 ("0.005, 0.025, 0.06, 0.1, 0.3");
values ( \
"1.1, 2.1, 3.1, 4.1, 5.1", \
"6.1, 7.1, 8.1, 9.1, 10.1", \
"11.1, 12.1, 13.1, 14.1, 15.1", \
"16.1, 17.1, 18.1, 19.1, 20.1", \
"21.1, 22.1, 23.1, 24.1, 25.1", \
);
}
}
你确实失去了所有漂亮的缩进,但你得到了你想要的值.
You do lose all your nice indentation, but you get the values you want.
这篇关于tcl 文本处理 - 根据用户定义的值重新排列行和列中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!