我有一个TCL脚本,说有30行自动化代码,这些代码我正在dc shell(Synopsys Design编译器)中执行。我要在第10行停止并退出脚本,退出dc shell,并在执行手动检查后再次将其重新备份。但是,这次,我想从第11行开始运行脚本,而不必执行前10行。
我不想使用两个脚本,一个脚本包含直到第10行的代码,而另一个脚本剩下其余的脚本,我想仅使用一个脚本并尝试从第N行执行它。>
类似:
source a.tcl -line 11
我该怎么做?
答案 0 :(得分:1)
如果您拥有Tcl 8.6+,并且考虑在Tcl coroutine上重新建模脚本,则可以在几行中实现这种延续行为。假设您是从交互式Tcl shell(dc shell?)运行脚本的。
# script.tcl
if {[info procs allSteps] eq ""} {
# We are not re-entering (continuing), so start all over.
proc allSteps {args} {
yield; # do not run when defining the coroutine;
puts 1
puts 2
puts 3
yield; # step out, once first sequence of steps (1-10) has been executed
puts 4
puts 5
puts 6
rename allSteps ""; # self-clean, once the remainder of steps (11-N) have run
}
coroutine nextSteps allSteps
}
nextSteps; # run coroutine
allSteps
)中。yield
表示第一步之后(例如,第十步之后)的保持/继续点。nextSteps
创建一个协程allSteps
。proc
和coroutine
的定义(当步骤待处理时)然后,启动您的交互式Shell并运行source script.tcl
:
% source script.tcl
1
2
3
现在,执行您的手动检查。然后,从同一外壳中继续:
% source script.tcl
4
5
6
请注意,您可以运行整个两阶段序列任意次(由于协程proc:rename
的自我清除):
% source script.tcl
1
2
3
% source script.tcl
4
5
6
再次:所有这些都假定您不退出shell,并在执行审阅时维护shell。如果出于某种原因(或无法运行Tcl 8.6+)需要退出shell,那么Donal的建议就是解决之道。
如果适用于您的情况,可以使用anonymous (lambda) proc改进实施。这简化了生命周期管理(避免重新定义,管理协程和proc,不需要rename
):
# script.tcl
if {[info commands nextSteps] eq ""} {
# We are not re-entering (continuing), so start all over.
coroutine nextSteps apply {args {
yield; # do not run when defining the coroutine;
puts 1
puts 2
puts 3
yield; # step out, once first sequence of steps (1-10) has been executed
puts 4
puts 5
puts 6
}}
}
nextSteps
答案 1 :(得分:0)
最简单的方法是打开文本文件,解析它以获得第一个 N 命令(info complete
在此处很有用),然后评估它们(或脚本的其余部分) )。当您删除尾部时,与删除前缀时相反,有效地执行此操作会产生稍有不同的代码。
proc ReadAllLines {filename} {
set f [open $filename]
set lines {}
# A little bit careful in case you're working with very large scripts
while {[gets $f line] >= 0} {
lappend lines $line
}
close $f
return $lines
}
proc SourceFirstN {filename n} {
set lines [ReadAllLines $filename]
set i 0
set script {}
foreach line $lines {
append script $line "\n"
if {[info complete $script] && [incr i] >= $n} {
break
}
}
info script $filename
unset lines
uplevel 1 $script
}
proc SourceTailN {filename n} {
set lines [ReadAllLines $filename]
set i 0
set script {}
for {set j 0} {$j < [llength $lines]} {incr j} {
set line [lindex $lines $j]
append script $line "\n"
if {[info complete $script]} {
if {[incr i] >= $n} {
info script $filename
set realScript [join [lrange $lines [incr j] end] "\n"]
unset lines script
return [uplevel 1 $realScript]
}
# Dump the prefix we don't need any more
set script {}
}
}
# If we get here, the script had fewer than n lines so there's nothing to do
}
请注意,您正在处理的文件种类可能会很大,并且Tcl当前有一些硬盘限制。另一方面,如果您完全可以source
文件,那么您已经在该限制之内…