如何使用Tcl正则表达式提取所有匹配项?

Mal*_*uri 7 regex tcl

大家好我想要这个正则表达式的解决方案,我的问题是提取表单中的所有十六进制数字H'xxxx,我使用这个正则表达式但我没有得到所有的十六进制只有我得到一个数字,如何从这个字符串获得整数十六进制数

set hex "V5CCH,IA=H'22EF&H'2354&H'4BD4&H'4C4B&H'4D52&H'4DC9"
set res [regexp -all {H'([0-9A-Z]+)&} $hex match hexValues]
puts "$res H$hexValues"
Run Code Online (Sandbox Code Playgroud)

我得到的输出是5 H4D52

pol*_*nts 25

-all -inline

文档:

-all:使正则表达式在字符串中尽可能多地匹配,返回找到的匹配总数.如果使用匹配变量指定,则它们将仅包含最后一个匹配的信息.

-inline:使命令以列表形式返回否则将放在匹配变量中的数据.使用时-inline,可能不指定匹配变量.如果与之一起使用-all,则列表将在每次迭代时连接,以便始终返回平面列表.对于每个匹配迭代,该命令将追加整体匹配数据,并为正则表达式中的每个子表达式添加一个元素.

因此,要返回所有匹配 - 包括按组捕获 - 作为Tcl中的平面列表,您可以写:

set matchTuples [regexp -all -inline $pattern $text]
Run Code Online (Sandbox Code Playgroud)

如果模式具有组0…N-1,则每个匹配N在列表中为-tuple.因此,实际匹配的数量是该列表的长度除以N.然后foreach,您可以使用N变量来迭代列表的每个元组.

如果N = 2举例来说,您有:

set numMatches [expr {[llength $matchTuples] / 2}]

foreach {group0 group1} $matchTuples {
   ...
}
Run Code Online (Sandbox Code Playgroud)

参考


示例代码

这是针对此特定问题的解决方案,使用输出作为注释进行注释(另请参见ideone.com):

set text "V5CCH,IA=H'22EF&H'2354&H'4BD4&H'4C4B&H'4D52&H'4DC9"
set pattern {H'([0-9A-F]{4})}

set matchTuples [regexp -all -inline $pattern $text]

puts $matchTuples
# H'22EF 22EF H'2354 2354 H'4BD4 4BD4 H'4C4B 4C4B H'4D52 4D52 H'4DC9 4DC9
# \_________/ \_________/ \_________/ \_________/ \_________/ \_________/
#  1st match   2nd match   3rd match   4th match   5th match   6th match

puts [llength $matchTuples]
# 12

set numMatches [expr {[llength $matchTuples] / 2}]
puts $numMatches
# 6

foreach {whole hex} $matchTuples {
   puts $hex
}
# 22EF
# 2354
# 4BD4
# 4C4B
# 4D52
# 4DC9
Run Code Online (Sandbox Code Playgroud)

在模式上

请注意,我稍微更改了模式:

  • 而不是[0-9A-Z]+,例如[0-9A-F]{4}更具体地匹配恰好4个十六进制数字
  • 如果您坚持匹配&,则H'4DC9无法匹配最后一个十六进制字符串(在您的输入中)
    • 这解释了为什么你进入4D52原始脚本,因为这是最后一次匹配&
    • 也许摆脱&,或使用(&|$)相反,即&字符串的一个或结束$.

参考

  • @polygene:+1:看起来很不错.如果你正在写更多的Tcl,记得把括号括起来(除非你*真的*知道你在做什么),因为这样可以编译它们并避免类似于SQL注入攻击的问题; 支撑表达是无危险和快速的. (2认同)