"whole" 在此 TCL foreach 循环(正则表达式)中的含义

Meaning of "whole" in this TCL foreach loop (regex)

我想了解“whole”关键字在下面的 foreach 循环中的作用。我写了一个正则表达式来查找 | 之间的数字和)在文本中。当我 运行 以下脚本时,请参阅下面的输出。

#!/usr/bin/expect

set text "A(1|1) B(1|3) C(1|6)"

#regex to find numbers between | and )
set pattern {\|([0-9]+)\)}  
                         
set matches [regexp -all -inline $pattern $text]

foreach {whole num} $matches {
        puts $num
}

puts "---"

foreach num $matches {
        puts $num
}

输出:

1
3
6
---
|1)
1
|3)
3
|6)
6

第一个循环输出是想要的,但是为什么当我删除“whole”关键字时第二个循环显示|1),|3)?

您的正则表达式有一个子组 ([0-9]+)。 因此,在应用 -inline 时,它将 return 包含整个匹配项和第一个子组的列表。

结果不仅限于第一个子组。它基于您提供给表达式的子组数量。例如

% regexp -inline {\d[a-z][A-Z]} "0bX"; # No subgroups
0bX
% regexp -inline {\d[a-z]([A-Z])} "0bX"; # subgroup only for upper-case letters
0bX X
% regexp -inline {\d([a-z])[A-Z]} "0bX"; # subgroup only for lower-case letters
0bX b
% regexp -inline {(\d)[a-z][A-Z]} "0bX"; # subgroup only for digits
0bX 0
% regexp -inline {(\d[a-z])[A-Z]} "0bX"; # subgroup only for digit-lower-case combination
0bX 0b
% regexp -inline {(\d[a-z])([A-Z])} "0bX"; # 1st subgroup is for digit-lower-case  and 2nd subgroup is for upper-case letter
0bX 0b X
% regexp -inline {(\d)([a-z])([A-Z])} "0bX"# 1st subgroup is for digit and 2nd subgroup is for lower-case letter and 3rd subgroup is for upper-case letter
0bX 0 b X
%

请注意,在所有这些结果中,始终首先提供整个匹配(即完整匹配),然后提供后续 n 个子组匹配。

这也适用于 -all 标志。因此,对所有匹配重复该过程。

现在,如果我们将此逻辑应用于您的代码,我们将得到以下结果

# 1st whole match, 1st whole match's 1st subgroup, 2nd whole match, 2nd match's 1st subgroup and so on    
% set matches [regexp -all -inline $pattern $text];
|1) 1 |3) 3 |6) 6
%

Regex101 Example

如您所知,regexp -all -inline 生成它匹配的事物的列表,其中该列表每个匹配有多个条目(第一个是完整匹配,后续条目是每个捕获子表达式);它的实际结果是 |1) 1 |3) 3 |6) 6foreachwhole 是怎么回事?

嗯,whole这个词一点也不特别。它只是一个变量名。那种foreach的一般形式是:

foreach listOfVariableNames listToIterateOver body

{whole num} 是一个包含两个变量名称的列表,因此通过 $matches 的每次迭代我们都会提取列表的两个元素并将它们分配给每个变量。如果尸体是:

puts "whole = '$whole' num = '$num'"

输出应该是:

whole = '|1)' num = '1'
whole = '|3)' num = '3'
whole = '|6)' num = '6'

因为您实际上并没有使用 whole,所以效果是忽略整体匹配,只使用子表达式匹配。这是一个相当常见的模式。