如果我匹配带有十个捕获的正则表达式:
/(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
?
红宝石似乎处理$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
顺便说一下,最大捕获组数是32,767,你可以访问所有通过$n
:
/#{'()' * 32768}/ #=> RegexpError: too many capture groups are specified /#{'()' * 32767}/ =~ '' #=> 0 defined? $32767 #=> "global-variable" $32767 #=> ""
返回的编号变量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核心团队的人.这似乎是武断的,但可能会有一些审议进入决策.