如何根据一些内部值清除嵌套的 tcl 列表
How to purge nested tcl list according to some internal value
我有一个脚本,其中包含以下格式:
set cmd "some command and -flags -parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format15} {bla bla} {param:{M15 more info}}}} -extra info"
我想从 cmd var 中清除所有带有 M11 及更高版本的项目,而不影响 cmd 的其余部分。
尝试将其视为列表,但我无法保证哪个列表元素将包含相关的嵌套列表。
是否有一种简单易用的方法来执行此清除,或者我必须通过 $cmd 变量来确定我的原因吗?
所需的输出应该是:
"some command and -flags -parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format10} {bla bla} {param:{M10 more info}}}} -extra info"
编辑:
使用 Donnel 的回答,我找到了这个解决方案:
for {set i 0} {$i < [llength $cmd]} {incr i} {
if {[llength [lindex $cmd $i] ] == 1} {continue}
set filtered [lmap p [lindex $cmd $i] {
if {[regexp {^parameters:\{M(\d+)} [lindex $p 2] -> val] && $val >= 11} { continue }
string cat $p
}]
break
}
set cmd [string cat [lrange $cmd 0 [expr $i -1]] " " $filtered " " [lrange $cmd [expr $i +1] end]]
美妙之处在于循环还可以在字符串中找到嵌套列表所在的位置,从而允许之后轻松连接字符串。
这绝对会很乱。
假设你有:
set parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format15} {bla bla} {param:{M15 more info}}}}
然后我们可以用 lmap
和 continue
:
过滤它们
set filtered [lmap p $parameters {
if {[regexp {^param:\{M(\d+)} [lindex $p 2] -> val] && $val >= 11} {
# Skips this item
continue
}
# Don't skip, don't further transform
string cat $p
}]
生成的列表在其元素方面将是等效的,除了被删除的项目。
我假设您感兴趣的用于确定是否过滤的值位于每个子列表的第三个元素中。如果它是 last 元素,那么 end
而不是 2
将更适合 lindex
。如果您必须搜索它,那要贵得多!你会这样做:
set filtered [lmap p $parameters {
set idx [lsearch -glob $p param:*]
if {$idx >= 0 && [regexp {^param:\{M(\d+)} [lindex $p $idx] -> val] && $val >= 11} {
# Skips this item
continue
}
# Don't skip, don't further transform
string cat $p
}]
但我真的希望你不需要那样做! (理论上它可能会更复杂,你的表现也会相应地受到影响。)
我有一个脚本,其中包含以下格式:
set cmd "some command and -flags -parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format15} {bla bla} {param:{M15 more info}}}} -extra info"
我想从 cmd var 中清除所有带有 M11 及更高版本的项目,而不影响 cmd 的其余部分。
尝试将其视为列表,但我无法保证哪个列表元素将包含相关的嵌套列表。
是否有一种简单易用的方法来执行此清除,或者我必须通过 $cmd 变量来确定我的原因吗?
所需的输出应该是:
"some command and -flags -parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format10} {bla bla} {param:{M10 more info}}}} -extra info"
编辑:
使用 Donnel 的回答,我找到了这个解决方案:
for {set i 0} {$i < [llength $cmd]} {incr i} {
if {[llength [lindex $cmd $i] ] == 1} {continue}
set filtered [lmap p [lindex $cmd $i] {
if {[regexp {^parameters:\{M(\d+)} [lindex $p 2] -> val] && $val >= 11} { continue }
string cat $p
}]
break
}
set cmd [string cat [lrange $cmd 0 [expr $i -1]] " " $filtered " " [lrange $cmd [expr $i +1] end]]
美妙之处在于循环还可以在字符串中找到嵌套列表所在的位置,从而允许之后轻松连接字符串。
这绝对会很乱。
假设你有:
set parameters {{{format1} {bla bla} {param:{M1 more info}}} \
{{format2} {bla bla} {param:{M2 more info}}} \
...
{{format15} {bla bla} {param:{M15 more info}}}}
然后我们可以用 lmap
和 continue
:
set filtered [lmap p $parameters {
if {[regexp {^param:\{M(\d+)} [lindex $p 2] -> val] && $val >= 11} {
# Skips this item
continue
}
# Don't skip, don't further transform
string cat $p
}]
生成的列表在其元素方面将是等效的,除了被删除的项目。
我假设您感兴趣的用于确定是否过滤的值位于每个子列表的第三个元素中。如果它是 last 元素,那么 end
而不是 2
将更适合 lindex
。如果您必须搜索它,那要贵得多!你会这样做:
set filtered [lmap p $parameters {
set idx [lsearch -glob $p param:*]
if {$idx >= 0 && [regexp {^param:\{M(\d+)} [lindex $p $idx] -> val] && $val >= 11} {
# Skips this item
continue
}
# Don't skip, don't further transform
string cat $p
}]
但我真的希望你不需要那样做! (理论上它可能会更复杂,你的表现也会相应地受到影响。)