I was debugging someone else's code and was trying to track down where in a maze of namespaces a particular piece of data was stored. This prompted me to create this little proc which lets you search all known variables for a given string.
It's very simplistic, but solved my problem du jour.
Bryan Oakley 18-Oct-2001
# finds variables whose value matches the given pattern. All variables
# in the given namespace and all children of the namespace are considered.
#
# pattern must be of the form expected by [string match]. Note that the
# pattern is fed directly to [string match]. So to find a string that
# contains the fragment foo you must specify a pattern of *foo*. Otherwise
# you'll only find variables that contain precisely "foo".
#
# This program returns a list. Each element is a string of the form
# "variablename: value".
proc vargrep {pattern {ns ::}} {
set result {}
# loop over all variables in the given namespace
foreach var [info vars ${ns}::*] {
if {[array exists $var]} {
# this is an array; search through all elements
foreach element [array names $var] {
if {[string match $pattern [set ${var}($element)]]} {
lappend result "${var}($element): [set ${var}($element)]"
}
}
} else {
# this is a scalar... search just the variable
if {[string match $pattern [set $var]]} {
lappend result "$var: [set $var]"
}
}
}
# now do the same for all children of this namespace
foreach child [namespace children $ns] {
set tmp [vargrep $pattern $child]
set result [concat $result $tmp]
}
return $result
}JMN 2004-05-19 Note the above code breaks for variable declarations where no value has yet been assigned. e.g
namespace eval test {
variable blah
}%vargrep something can't read "::test::blah": no such variable %array exists ::blah::hmm 0 %info exists ::blah::hmm 0
I'd suggest wrapping the scalar if {[string match ... section in a simple catch. (rather than an info exists, as presumably such cases are the exception)