nichollsg
nichollsg

Reputation: 390

String pattern matching with tcl

I am new to tcl and am trying to only capture a user-specified hierarchy depth of the following:

top.run.end
top.run.something.end

top.simple.end1     
top.simple.end2

top.simple.something.end1
top.simple.something.end2

top.simple.something.else.end    
top.simple.something.else.other.name.end

I would like to only capture the final element in a hierarchy that does not continue with more elements deliminated by a ".". I.e. I would like to append all instances to a list (final element name could be anything).

If the user wants to select the 2nd hierarchy level, the comparison should only allow these elements from above:

top.run.end
top.simple.end1     
top.simple.end2

If the user specifies the 3rd hierarchy level, then I would like to grab these elements:

top.simple.something.end1
top.simple.something.end2

4th hierarchy level:

top.simple.something.else.end

So on and so forth... I have all the code written except the string comparison, but everything I've tried doesn't seem to do what I want.

set num_hierarchy 3; # how many levels deap to search for "end"
set num_facs      [ gtkwave::getNumFacs ]; # returns number of elements in file

for {set group_to_add 1} {$group_to_add <= $num_hierarchy} {incr group_to_add} {
    set wave [list]

    for {set i 0} {$i < $num_facs } {incr i} {
        set fac_name [ gtkwave::getFacName $i ]; #returns string in form noted above

        set indx [string <how to compare strings??> $fac_name]
        if {$indx == <match>} {
            lappend wave "$fac_name"
        } 
    }
}

Upvotes: 1

Views: 341

Answers (1)

Jerry
Jerry

Reputation: 71538

I can't say I understand why you are doing the loops like in your question, so I'll show a slightly different code snippet. I believe you should easily be able to implement the solution in your own if I can show you how mine works. The matching is done by counting the number of dots:

set elements {
  top.run.end
  top.run.something.end
  top.simple.end1     
  top.simple.end2
  top.simple.something.end1
  top.simple.something.end2
  top.simple.something.else.end    
  top.simple.something.else.other.name.end
}

set depth_required 3
set wave [list]

foreach element $elements {
  # initial length of element
  set i_len [string length $element]

  # final length of element after removing dots
  set f_len [string length [string map {. ""} $element]]

  # thus number of dots
  set n_dots [expr {$i_len-$f_len}]

  # if the number equals the required hierarchy, then we got one
  if {$n_dots == $depth_required} {
    lappend wave $element
  }
}

wave then contains:

top.run.something.end top.simple.something.end1 top.simple.something.end2

You could use regsub (which can directly return the number of substitutions performed) or split the element on dots then count of the number of resulting sub-elements as well, but I found this wiki where it shows using string map is the fastest method overall.

Upvotes: 1

Related Questions