Соответствие строковому образцу с tcl

Я новичок в tcl и пытаюсь захватить только заданную пользователем глубину иерархии следующего:

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

Я хотел бы захватить только последний элемент в иерархии, которая не продолжается с большим количеством элементов, ограниченных символом ".". Т.е. я хотел бы добавить все экземпляры в список (конечное имя элемента может быть любым).

Если пользователь хочет выбрать 2-й уровень иерархии, сравнение должно разрешить только эти элементы сверху:

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

Если пользователь указывает 3-й уровень иерархии, я хотел бы получить эти элементы:

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

4-й уровень иерархии:

top.simple.something.else.end

И так далее, и тому подобное... У меня есть весь написанный код, кроме сравнения строк, но все, что я пробовал, похоже, не выполняет то, что я хочу.

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"
        } 
    }
}

1 ответ

Решение

Я не могу сказать, что понимаю, почему вы делаете циклы, как в вашем вопросе, поэтому я покажу немного другой фрагмент кода. Я считаю, что вы легко сможете реализовать решение самостоятельно, если я покажу вам, как работает мой. Сопоставление выполняется путем подсчета количества точек:

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 затем содержит:

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

Вы могли бы использовать regsub (который может напрямую возвращать количество выполненных подстановок) или разделить элемент на точки, а затем подсчитать количество полученных подэлементов, но я нашел эту вики, где она показывает, используя string map самый быстрый метод в целом.

Другие вопросы по тегам