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

Regex 如何使用Tcl正则表达式提取所有匹配项?,regex,tcl,Regex,Tcl,大家好,我想要这个正则表达式的解决方案,我的问题是提取表单H'xxxx中的所有十六进制数,我使用了这个regexp,但我没有得到所有的十六进制值,我只得到一个数,如何从这个字符串中得到整个十六进制数 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

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

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"

我得到的输出是5 H4D52

我不是Tlish,但我认为您需要同时使用
-inline
-all
选项:

regexp -all -inline {H'([0-9A-Z]+)&} $string
编辑:再次出现,这一次使用了更正的正则表达式(请参见注释):

-all-inline上
发件人:

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

-inline
:使命令以列表的形式返回原本放置在匹配变量中的数据。使用
-inline
时,可能不会指定匹配变量。如果与
-all
一起使用,列表将在每次迭代时连接起来,以便始终返回一个平面列表。对于每个匹配迭代,该命令将附加整个匹配数据,以及正则表达式中每个子表达式的一个元素

因此,要在Tcl中将所有匹配项(包括按组捕获)作为平面列表返回,您可以编写:

set matchTuples [regexp -all -inline $pattern $text]
如果模式具有组
0…N-1
,则每个匹配项都是列表中的
N
-元组。因此,实际匹配的数量是该列表的长度除以
N
。然后,您可以使用
foreach
N
变量对列表的每个元组进行迭代

例如,如果
N=2
,您有:

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

foreach {group0 group1} $matchTuples {
   ...
}
工具书类

示例代码 下面是这个特定问题的解决方案,用输出注释():


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

  • 而不是
    [0-9A-Z]+
    ,例如
    [0-9A-F]{4}
    更适合精确匹配4个十六进制数字
  • 如果您坚持要匹配
    &
    ,则无法匹配输入中的最后一个十六进制字符串(
    H'4DC9
    • 这解释了为什么原始脚本中会出现
      4D52
      ,因为这是与
      &
    • 可以去掉
      &
      ,或者改用
      (&|$)
      ,即
      &
      或字符串的结尾
      $
工具书类
  • ,

我想知道单引号是否需要转义?:H\'([0-9A-Z]+)\&如果您处理的是十六进制数,[0-9A-F]应该足够了。@Zabba,单引号在正则表达式中,甚至在一般的Tcl中都没有特殊意义。@relet,这也有效:
[:xdigit:]
--谢谢,我不知道在这种情况下十六进制的计数如何计算?@polygen我尝试过数组操作,数组大小仅显示最后一个元素存储在该元素中的一次,请提供该元素的示例。@polygene:我建议您将其编辑到您的答案中,因为这是惯用的方法。@polygene:+1:看起来不错。如果您正在编写更多的Tcl,请记住在表达式周围加大括号(除非您真的知道自己在做什么),因为这样可以编译表达式并避免类似于SQL注入攻击的问题;大括号表达式是无危险且快速的。@Donal研究了如何在regexp中使用-about选项,但-inline输出提供了类似于regexp的-all{H'(0-9A-Z]+)&}$string match put$match我们也可以编写这个。上面的regexp是product H'22EF&22EF H'2354&2354 H'4BD4&4BD4 H'4C4B&4C4B H'4D52&4D52我不想要这个输出我只需要十六进制值我只是演示了
-all-inline
的用法,但是@poly是对的:你需要去掉那些括号。分组时不需要它们,它们向结果数组中添加了许多不需要的子字符串。
set numMatches [expr {[llength $matchTuples] / 2}]

foreach {group0 group1} $matchTuples {
   ...
}
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