Sed:在每个TCL进程的开始处添加一行

Sed:在每个TCL进程的开始处添加一行,sed,tcl,Sed,Tcl,我有一个像这样的TCL进程,希望在进程开始后添加一行,即输入myproc行的put proc myproc { {filename "input.txt"} {var1 "x"} {var2 "y"} {var3 "z"} {var4 ""} {var5 "0"} {var6 "0"} {var7 0} } { puts " entered myproc" 你能帮忙吗? &它也应该适用于 proc myproc2{N val}{ 输入myproc 评论行 集合ret{}用于{set i 0}

我有一个像这样的TCL进程,希望在进程开始后添加一行,即输入myproc行的put

proc myproc { {filename "input.txt"}
{var1 "x"} 
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
你能帮忙吗? &它也应该适用于 proc myproc2{N val}{ 输入myproc 评论行 集合ret{}用于{set i 0}{$i<$N}{incr i}{lappend ret$val} 返回$ret }

使用awk,您可以执行以下操作:

awk '/^ *proc/ {$0 = $0 "\nputs \" entered myproc\""} 1' RS= proc-file.tcl
提供此文件:

proc myproc { {filename "input.txt"}
{var1 "x"} 
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"

如果您只想获取代码的执行跟踪,比如调用堆栈转储等,那么您根本不需要修改源代码。您可以使用tcl本身来为您做这件事

Tcl没有保留关键字,一个也没有。甚至连proc都没有保留。因此,您可以重新定义它:

rename proc _proc

# Now proc no longer exists but we have _proc instead.
# Use it to redefine "proc":

_proc proc {name arguments body} {
    set body "puts \"entered $name\";$body"
    _proc $name $arguments $body
}
只需在运行任何自己的代码之前执行此操作,您就会发现在每次调用中输入的每个过程都会打印出来

许多tcl调试器和分析器就是这样工作的——使用tcl来重新定义自己

从您的评论来看,您似乎还试图打印每个调用的堆栈深度。要做到这一点,您需要向每个过程定义添加更多代码。最直接的方法当然是这样的:

_proc proc {name arguments body} {
    set preamble"set dist2top \[info level\];puts \"\$dist2top entered $name\""
    set body "$preamble;$body"
    _proc $name $arguments $body
}
但正如您所看到的,在字符串中编写代码很快就会变得不可管理。有几种技巧可以让它更易于管理。其中一种更常见的方法是按行拆分$body,并使用list命令来操作代码。它至少应该减少引用地狱的一个级别。我最喜欢的是使用类似于在MVC框架中编写html模板的模板技术。我通常使用字符串映射:

_proc proc {name arguments body} {
    _proc $name $arguments [string map [list %NAME% $name %BODY% $body] {
        set dist2top [info level]
        puts "$dist2top entered: %NAME%"
        %BODY%
    }]
}

_proc定义中的最后一个参数只是一个字符串,但它看起来像一个代码块,因此更易于阅读。这种技术没有恶意的引用。

每个Var1/2/3..都在一行上,因为它的大小&一些遗留的代码格式化您的问题,并提供示例输入和输出。下面是文件中的示例,上面是示例输出文件,我只需要添加一个字符串,如put:proc myproc{filename input.txt}{Var1 x}{var2 y}{var3 z}{var4}{var5 0}{var6 0}{var7 0}}{你为什么需要这样做?想在每个进程开始之前执行一个进程,这样我就可以得到调用堆栈/或进程名,这取决于调试我在做什么,但是,它希望它查找进程,一行的开始&查找有}的行{现在可以工作了。但是如何更新这个文件呢?还有,它是如何工作的,你也可以发布一个注释版本吗?你可以这样做:awk'/^*proc/{$0=$0\nputs\entered myproc\}1'RS=proc-file.tcl>\u tmp&&mv\u tmp proc-file.tcl但是,像这样的程序失败了&在函数之外添加了put..proc myproc 2{N val}{comment line set ret}}对于{set i 0}{$i<$N}{incr i}{lappend ret$val}返回$ret}同样,对于某些进程,在头中的行数不同的情况下,它以与}不同的偏移量打印它们{match.但是我无法获得整个堆栈:重命名proc{u proc Now proc不再存在,但是我们有了{u proc。使用它来重新定义proc:{u proc proc{name arguments body}{set distancetoop[info level]set body put\$distancetoop:entered$name\$body}proc$name$arguments$body}proc A{{B 3}proc B{x}{C[incr x]2}proc{x y{z 5}{D[incr x][incr y]$z}proc D{x y z}{E[incr x][incr y][incr z]}proc E{x y][incr z}{puts in proc E set distancetoop[info level]将进程内到top的距离设置为:$distancetoop}输出:>A 1:输入A 1:输入B 1:输入C 1:输入D 1:输入E在过程中到过程内部顶部的距离E是:5您调用信息级别太早了。您需要在$body中调用它,而不是在定义过程时。