为什么只有有限数量的正则表达式捕获存储在“global_variables”中?

Why are only a limited number of regular expression captures stored in `global_variables`?

如果我用包含十个捕获的正则表达式进行匹配:

/(o)(t)(th)(f)(fi)(s)(se)(e)(n)(t)/.match("otthffisseent")

然后,对于 </code>,我得到:</p> <pre><code> # => "t"

global_variables 中没有。我得到(在 irb 会话中):

[:$;, :$-F, :$@, :$!, :$SAFE, :$~, :$&, :$`, :$', :$+, :$=, :$KCODE, :$-K, :$,,
 :$/, :$-0, :$\, :$_, :$stdin, :$stdout, :$stderr, :$>, :$<, :$., :$FILENAME,
 :$-i, :$*, :$?, :$$, :$:, :$-I, :$LOAD_PATH, :$", :$LOADED_FEATURES,
 :$VERBOSE, :$-v, :$-w, :$-W, :$DEBUG, :$-d, :[=13=], :$PROGRAM_NAME, :$-p, :$-l,
 :$-a, :$binding, :, :, :, :, :, :, :, :, :]

这里只列出前九个:

, :, :, :, :, :, :, :, :

这也得到了证实:

global_variables.include?(:) # => false

</code> 存储在哪里,为什么不存储在 <code>global_variables 中?

Kernel#global_variables 编辑的编号变量 return 将始终相同,即使在分配之前也是如此。 IE。 </code> 到 <code> 甚至在您进行匹配之前就会被 return 编辑,并且匹配更多的不会添加到列表中。 (它们也可以不赋值,例如使用 = "foo"。)

考虑方法的源代码:

VALUE
rb_f_global_variables(void)
{
    VALUE ary = rb_ary_new();
    char buf[2];
    int i;

    st_foreach_safe(rb_global_tbl, gvar_i, ary);
    buf[0] = '$';

    for (i = 1; i <= 9; ++i) {
        buf[1] = (char)(i + '0');
        rb_ary_push(ary, ID2SYM(rb_intern2(buf, 2)));
    }

    return ary;
}

您可以(在习惯了查看 C 之后)从 for 循环中看到符号 </code> 到 <code> 被硬编码到方法的 return 值中。

那么,如果 global_variables 的输出没有改变,你还能使用 </code> 吗?好吧,输出可能有点误导,因为它表明您的匹配数据存储在单独的变量中,但这些只是快捷方式,委托给存储在 <code>$~.[=26= 中的 MatchData 对象]

本质上是$n$~[n]。您会发现此 MatchData 对象(来自全局 table)是该方法原始输出的一部分,但在您进行匹配之前不会分配它。

至于在函数输出中包含 </code> 到 <code> 的理由是什么,您需要询问 Ruby 核心团队中的某个人。这似乎是武断的,但可能是经过深思熟虑后做出的决定。

Ruby 似乎在解析器级别处理 </code>、<code> 等:

ruby --dump parsetree_with_comment -e '0'

输出:

###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# | # new scope
# | # format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body
# +- nd_tbl (local table): (empty)
# +- nd_args (arguments):
# |   (null node)
# +- nd_body (body):
#     @ NODE_NTH_REF (line: 1)
#     | # nth special variable reference
#     | # format: $[nd_nth]
#     | # example: , , ..
#     +- nd_nth (variable): 0

顺便说一句,maximum number of capture groups 是 32,767,您可以通过 $n:

访问所有内容
/#{'()' * 32768}/       #=> RegexpError: too many capture groups are specified

/#{'()' * 32767}/ =~ '' #=> 0
defined? 767         #=> "global-variable"
767                  #=> ""

我们将此行为视为一个错误。我们在后备箱中修复了这个问题。