tcl 中的正则表达式太复杂错误
Regular expression is too complex error in tcl
小列表我还没有看到这个错误。当列表超过 10k 时弹出问题。 tcl 中正则表达式模式的数量是否有限制?
puts "#LEVELSHIFTER_TEMPLATES_LIMITSFILE:$perc_limit(levelshifter_templates)"
puts "#length of templates is :[llength $perc_limit(levelshifter_templates)]"
if { [regexp [join $perc_limit(levelshifter_templates) |] $temp] }
#LEVELSHIFTER_TEMPLATES_LIMITSFILE:HDPELT06_LVLDBUF_CAQDP_1 HDPELT06_LVLDBUF_CAQDPNRBY2_1 HDPELT06_LVLDBUF_CAQDP_1....
#length of templates is :13520
ERROR: couldn't compile regular expression pattern: regular expression is too complex
假设您想查看 temp
中的值是否与 perf_limit(levelshifter_templates)
中的列表元素之一完全匹配,这里有一些比尝试使用常规方法更好的方法表达式:
使用 lsearch
`:
# Sort the list after populating it so we can do an efficient binary search
set perf_limit(levelshifter_templates) [lsort $perf_limit(levelshifter_templates)]
# ...
# See if the value in temp exists in the list
if {[lsearch -sorted $perf_limit(levelshifter_templates) $temp] >= 0} {
# ...
}
提前将列表的元素存储在字典(如果您愿意,也可以是数组)中以进行 O(1)
查找:
foreach item $perf_limit(levelshifter_templates) {
dict set lookup $item 1
}
# ...
if {[dict exists $lookup $temp]} {
# ...
}
如果 $temp
是一个单词,而您实际上只是在进行文字测试,则应该反转检查。最简单的方法之一可能是:
if {$temp in $perc_limit(levelshifter_templates)} {
# ...
}
但是如果你经常这样做(好吧,不止几次,比如 3 或 4 次)那么最好为此构建一个字典:
# A one-off cost
foreach key $perc_limit(levelshifter_templates) {
# Value is arbitrary
dict set perc_limit_keys $key 1
}
# This is now very cheap
if {[dict exists $perc_limit_keys $temp]} {
# ...
}
如果你在 $temp
中有多个单词,拆分并检查(使用第二种技术,现在绝对值得)。这是一个辅助程序可能是个好计划的地方。
proc anyWordIn {inputString keyDictionary} {
foreach word [split $inputString] {
if {[dict exists $keyDictionary $word]} {
return true
}
}
return false
}
if {[anyWordIn $temp $perc_limit_keys]} {
# ...
}
我找到了解决此问题的简单解决方法,即使用 foreach 语句遍历列表中的所有正则表达式,而不是加入它们并进行搜索,但超长列表失败了。
foreach pattern $perc_limit(levelshifter_templates) {
if { [regexp $pattern $temp]}
#puts "$fullpath: [is_std_cell_dev $dev]"
puts "##matches: $pattern return 0"
return 0
}
}
小列表我还没有看到这个错误。当列表超过 10k 时弹出问题。 tcl 中正则表达式模式的数量是否有限制?
puts "#LEVELSHIFTER_TEMPLATES_LIMITSFILE:$perc_limit(levelshifter_templates)"
puts "#length of templates is :[llength $perc_limit(levelshifter_templates)]"
if { [regexp [join $perc_limit(levelshifter_templates) |] $temp] }
#LEVELSHIFTER_TEMPLATES_LIMITSFILE:HDPELT06_LVLDBUF_CAQDP_1 HDPELT06_LVLDBUF_CAQDPNRBY2_1 HDPELT06_LVLDBUF_CAQDP_1....
#length of templates is :13520
ERROR: couldn't compile regular expression pattern: regular expression is too complex
假设您想查看 temp
中的值是否与 perf_limit(levelshifter_templates)
中的列表元素之一完全匹配,这里有一些比尝试使用常规方法更好的方法表达式:
使用 lsearch
`:
# Sort the list after populating it so we can do an efficient binary search
set perf_limit(levelshifter_templates) [lsort $perf_limit(levelshifter_templates)]
# ...
# See if the value in temp exists in the list
if {[lsearch -sorted $perf_limit(levelshifter_templates) $temp] >= 0} {
# ...
}
提前将列表的元素存储在字典(如果您愿意,也可以是数组)中以进行 O(1)
查找:
foreach item $perf_limit(levelshifter_templates) {
dict set lookup $item 1
}
# ...
if {[dict exists $lookup $temp]} {
# ...
}
如果 $temp
是一个单词,而您实际上只是在进行文字测试,则应该反转检查。最简单的方法之一可能是:
if {$temp in $perc_limit(levelshifter_templates)} {
# ...
}
但是如果你经常这样做(好吧,不止几次,比如 3 或 4 次)那么最好为此构建一个字典:
# A one-off cost
foreach key $perc_limit(levelshifter_templates) {
# Value is arbitrary
dict set perc_limit_keys $key 1
}
# This is now very cheap
if {[dict exists $perc_limit_keys $temp]} {
# ...
}
如果你在 $temp
中有多个单词,拆分并检查(使用第二种技术,现在绝对值得)。这是一个辅助程序可能是个好计划的地方。
proc anyWordIn {inputString keyDictionary} {
foreach word [split $inputString] {
if {[dict exists $keyDictionary $word]} {
return true
}
}
return false
}
if {[anyWordIn $temp $perc_limit_keys]} {
# ...
}
我找到了解决此问题的简单解决方法,即使用 foreach 语句遍历列表中的所有正则表达式,而不是加入它们并进行搜索,但超长列表失败了。
foreach pattern $perc_limit(levelshifter_templates) {
if { [regexp $pattern $temp]}
#puts "$fullpath: [is_std_cell_dev $dev]"
puts "##matches: $pattern return 0"
return 0
}
}