我正试着写一些tcl代码,它将精确地定义开始标记和结束标记之间的所有内容,并将每个事件作为一个条目放入数组中。
我的开始标签是module
,结束标签是endmodule
。我把\b
放在它周围,所以它只匹配边界。我使用.*?
,所以它是一个非贪婪匹配。
示例字符串verilog_string
是:
set verilog_string {
module first_module;
// Verilog code
//jhkjhkh
endmodule
non-module code
123
456...
module second_module;
//code2
//lkjkjljk
//jkjhkhjkjhkh
endmodule
}
阵列位置1应包含:
module first_module;
// Verilog code
//jhkjhkh
endmodule
阵列位置2应包含:
module second_module;
//code2
//lkjkjljk
//jkjhkhjkjhkh
endmodule
以下是我目前掌握的情况:
尝试1
proc extract_verilog_modules {verilog_string} {
set content $verilog_string
set modules_list {}
# Match 'module' to 'endmodule' including multiline matches
set module_pattern {\bmodule\b.*?\bendmodule\b}
foreach module [regexp -all -inline $module_pattern $content] {
puts "here"
lappend modules_list $module
}
return $modules_list
}
set extracted_modules [extract_verilog_modules $verilog_string]
puts "here 1"
foreach module $extracted_modules {
puts "Extracted Module:\n$module"
}
puts "here 2"
尝试2
proc extract_verilog_modules {verilog_string} {
set content $verilog_string
set modules_list {}
set module_pattern {(?m)^\s*module\b.*?(?:(?=\n\s*endmodule\b)|(?=endmodule\b))}
set endmodule_pattern {endmodule\b}
foreach module_match [regexp -all -inline -- $module_pattern $content] {
set line_number [lsearch -inline -regexp [split $content "\n"] [string trimleft $module_match]]
set char_position [string first $module_match $line_number]
set module_content ""
set in_module 1
foreach line [split $module_match "\n"] {
if {$in_module} {
append module_content "$line\n"
}
if {[regexp $endmodule_pattern $line]} {
set in_module 0
}
}
lappend modules_list [list $module_content $line_number $char_position]
}
return $modules_list
}
尝试3
proc extract_verilog_modules {verilog_string} {
set content [string map {"\t" " "} $verilog_string]
set content [regsub -all {(?:\r?\n|\n\r)} $content "\t"]
set modules_list {}
set module_pattern {\s*module\b}
set endmodule_pattern {endmodule\b}
set module_index 0
set endmodule_index 0
while {[regexp -start $module_index -- $module_pattern $content -> module_start]} {
set module_end [expr {$module_start + $module_index + [string length "module"]}]
set module_index [expr {$module_end}]
if {[regexp -start $endmodule_index -- $endmodule_pattern $content -> endmodule_start]} {
set endmodule_end [expr {$endmodule_start + $endmodule_index + [string length "endmodule"]}]
set endmodule_index [expr {$endmodule_end}]
set module_content [string range $content $module_start $endmodule_end]
set module_content [string map {"\t" "\n"} $module_content]
set original_content [string map {"\t" "\n"} $content]
set lines [split $original_content "\n"]
set line_number 1
foreach line $lines {
if {[string first $module_content $line] >= 0} {
break
}
incr line_number
}
set char_position [string first $module_content $line]
lappend modules_list [list $module_content $line_number $char_position]
} else {
break
}
}
if {[llength $modules_list] == 0} {
puts "No matches found for the regex pattern."
}
return $modules_list
}
但是我没有输出。
2条答案
按热度按时间dly7yett1#
与documented一样,在Tcl正则表达式中,
\b
匹配退格字符(ASCII 0x 7 F)。单词边界由\y
匹配(如果您想具体说明单词的哪一个结尾,则可以使用\m
或\M
匹配;通常不需要)。[编辑]:有了你的样品,我得到了正确的东西:
我们需要一个更复杂的RE,因为模块只有在后面跟着模块名(与
\w+
匹配)和分号时才真正开始。如果没有这些,我们就会被non-module
搞糊涂。there中的
?
是 critical,必须放在 * 第一个量词 *(或所有量词)上才能为整个RE选择非贪婪。(我只能解释这一点;贪婪会影响RE编译到哪种自动机,并且在第一个量词时做出决定,但是RE编译器对什么是第一个量词有一些奇怪的想法。实际上,我只是测试了这个,直到它工作!)我假设没有注解格式需要注意。如果注解格式很重要,RE会变得相当长,匹配也会更加复杂。
r7s23pms2#
我发现ActiveState TCL不支持\B的字边界。我不得不使用一个较旧的语法::〈:模块:〉:]