如果我与正则表达式匹配10个捕获:
/(o)(t)(th)(f)(fi)(s)(se)(e)(n)(t)/.match("otthffisseent")
然后,对于$10
,我得到:
$10 # => "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, :$0, :$PROGRAM_NAME, :$-p, :$-l,
:$-a, :$binding, :$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9]
此处仅列出前九个:
$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9
这也得到了以下证实:
global_variables.include?(:$10) # => false
$10
存储在哪里,为什么不存储在global_variables
?
答案 0 :(得分:9)
Ruby似乎在解析器级别处理$1
,$2
等:
ruby --dump parsetree_with_comment -e '$100'
输出:
###########################################################
## 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: $1, $2, ..
# +- nd_nth (variable): $100
BTW,maximum number of capture groups为32,767,您可以通过$n
访问所有内容:
/#{'()' * 32768}/ #=> RegexpError: too many capture groups are specified
/#{'()' * 32767}/ =~ '' #=> 0
defined? $32767 #=> "global-variable"
$32767 #=> ""
答案 1 :(得分:6)
从Kernel#global_variables
返回的编号变量将始终相同,即使在分配之前也是如此。即即使在您进行匹配之前,也会返回$1
到$9
,并且匹配更多内容将不会添加到列表中。 (也不能分配它们,例如使用$10 = "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循环中看到符号$1
到$9
被硬编码到方法的返回值中。
那么,如果$10
的输出没有改变,你还可以使用global_variables
吗?好吧,输出可能有点误导,因为它会建议你的匹配数据存储在单独的变量中,但这些只是快捷方式,委托给MatchData
中存储的$~
对象。
基本上$n
关注$~[n]
。您会发现此MatchData
对象(来自全局表)是该方法的原始输出的一部分,但在您进行匹配之前不会分配它。
关于在函数输出中包含$1
到$9
的理由是什么,您需要向Ruby核心团队中的某个人询问。这可能看起来是武断的,但可能会有一些审议意见。
答案 2 :(得分:3)
我们将此行为视为错误。我们把它固定在后备箱里。