class StringScanner
公共类方法
返回一个新的 StringScanner
对象,其 [存储的 字符串] 是给定的 string
;设置 [固定锚点 属性]
scanner = StringScanner.new('foobarbaz') scanner.string # => "foobarbaz" scanner.fixed_anchor? # => false put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: "foobarbaz" # rest_size: 9
static VALUE strscan_initialize(int argc, VALUE *argv, VALUE self) { struct strscanner *p; VALUE str, options; p = check_strscan(self); rb_scan_args(argc, argv, "11", &str, &options); options = rb_check_hash_type(options); if (!NIL_P(options)) { VALUE fixed_anchor; ID keyword_ids[1]; keyword_ids[0] = rb_intern("fixed_anchor"); rb_get_kwargs(options, keyword_ids, 0, 1, &fixed_anchor); if (fixed_anchor == Qundef) { p->fixed_anchor_p = false; } else { p->fixed_anchor_p = RTEST(fixed_anchor); } } else { p->fixed_anchor_p = false; } StringValue(str); p->str = str; return self; }
公共实例方法
scanner = StringScanner.new('foo') scanner.string # => "foo" scanner.terminate scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba..."> scanner.string # => "foobarbaz" put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "barbaz" # rest_size: 6
返回捕获的子字符串或 nil
;请参阅 [捕获的匹配 值]。
当存在捕获时
scanner = StringScanner.new('Fri Dec 12 1975 14:39') scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
-
specifier
为零:返回整个匹配的子字符串scanner[0] # => "Fri Dec 12 " scanner.pre_match # => "" scanner.post_match # => "1975 14:39"
-
specifier
为正整数:返回第n
个捕获,如果超出范围则返回nil
scanner[1] # => "Fri" scanner[2] # => "Dec" scanner[3] # => "12" scanner[4] # => nil
-
specifier
为负整数:从最后一个子组向后计数scanner[-1] # => "12" scanner[-4] # => "Fri Dec 12 " scanner[-5] # => nil
-
specifier
为符号或字符串:返回命名子组,如果没有则返回nil
scanner[:wday] # => "Fri" scanner['wday'] # => "Fri" scanner[:month] # => "Dec" scanner[:day] # => "12" scanner[:nope] # => nil
当没有捕获时,只有 [0]
返回非 nil
scanner = StringScanner.new('foobarbaz') scanner.exist?(/bar/) scanner[0] # => "bar" scanner[1] # => nil
对于失败的匹配,即使 [0]
也返回 nil
scanner.scan(/nope/) # => nil scanner[0] # => nil scanner[1] # => nil
static VALUE strscan_aref(VALUE self, VALUE idx) { const char *name; struct strscanner *p; long i; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; switch (TYPE(idx)) { case T_SYMBOL: idx = rb_sym2str(idx); /* fall through */ case T_STRING: if (!RTEST(p->regex)) return Qnil; RSTRING_GETMEM(idx, name, i); i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx)); break; default: i = NUM2LONG(idx); } if (i < 0) i += p->regs.num_regs; if (i < 0) return Qnil; if (i >= p->regs.num_regs) return Qnil; if (p->regs.beg[i] == -1) return Qnil; return extract_range(p, adjust_register_position(p, p->regs.beg[i]), adjust_register_position(p, p->regs.end[i])); }
返回 [位置] 是否位于行首;即,位于 [存储的 字符串] 的开头或紧跟换行符之后
scanner = StringScanner.new(MULTILINE_TEXT) scanner.string # => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n" scanner.pos # => 0 scanner.beginning_of_line? # => true scanner.scan_until(/,/) # => "Go placidly amid the noise and haste," scanner.beginning_of_line? # => false scanner.scan(/\n/) # => "\n" scanner.beginning_of_line? # => true scanner.terminate scanner.beginning_of_line? # => true scanner.concat('x') scanner.terminate scanner.beginning_of_line? # => false
StringScanner#bol? 是 StringScanner#beginning_of_line?
的别名。
static VALUE strscan_bol_p(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (CURPTR(p) > S_PEND(p)) return Qnil; if (p->curr == 0) return Qtrue; return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse; }
如果最近的匹配尝试成功,则返回索引为 (1..)
的 [捕获的匹配 值] 数组,否则返回 nil
scanner = StringScanner.new('Fri Dec 12 1975 14:39') scanner.captures # => nil scanner.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) scanner.captures # => ["Fri", "Dec", "12"] scanner.values_at(*0..4) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil] scanner.exist?(/Fri/) scanner.captures # => [] scanner.scan(/nope/) scanner.captures # => nil
static VALUE strscan_captures(VALUE self) { struct strscanner *p; int i, num_regs; VALUE new_ary; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; num_regs = p->regs.num_regs; new_ary = rb_ary_new2(num_regs); for (i = 1; i < num_regs; i++) { VALUE str; if (p->regs.beg[i] == -1) str = Qnil; else str = extract_range(p, adjust_register_position(p, p->regs.beg[i]), adjust_register_position(p, p->regs.end[i])); rb_ary_push(new_ary, str); } return new_ary; }
static VALUE strscan_get_charpos(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str))); }
尝试在 [目标 子字符串] 的开头 [匹配] 给定的 pattern
;不修改 [位置]。
如果匹配成功
-
返回匹配的子字符串。
-
设置所有 [匹配 值]。
scanner = StringScanner.new('foobarbaz') scanner.pos = 3 scanner.check('bar') # => "bar" put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: "foo" # matched : "bar" # post_match: "baz" # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: ["bar", nil] # []: # [0]: "bar" # [1]: nil # => 0..1 put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "barbaz" # rest_size: 6
如果匹配失败
-
返回
nil
。 -
清除所有 [匹配 值]。
scanner.check(/nope/) # => nil match_values_cleared?(scanner) # => true
static VALUE strscan_check(VALUE self, VALUE re) { return strscan_do_scan(self, re, 0, 1, 1); }
尝试在 [目标 子字符串] 中的任何位置(在任何 [位置]) [匹配] 给定的 pattern
;不修改 [位置]。
如果匹配成功
scanner = StringScanner.new('foobarbazbatbam') scanner.pos = 6 scanner.check_until(/bat/) # => "bazbat" put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: "foobarbaz" # matched : "bat" # post_match: "bam" # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: ["bat", nil] # []: # [0]: "bat" # [1]: nil put_situation(scanner) # Situation: # pos: 6 # charpos: 6 # rest: "bazbatbam" # rest_size: 9
如果匹配失败
-
清除所有 [匹配 值]。
-
返回
nil
。
scanner.check_until(/nope/) # => nil match_values_cleared?(scanner) # => true
static VALUE strscan_check_until(VALUE self, VALUE re) { return strscan_do_scan(self, re, 0, 1, 0); }
scanner = StringScanner.new('foo') scanner.string # => "foo" scanner.terminate scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba..."> scanner.string # => "foobarbaz" put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "barbaz" # rest_size: 6
static VALUE strscan_concat(VALUE self, VALUE str) { struct strscanner *p; GET_SCANNER(self, p); StringValue(str); rb_str_append(p->str, str); return self; }
尝试在 [目标 子字符串] 中的任何位置(在任何 [位置]) [匹配] 给定的 pattern
;不修改 [位置]。
如果匹配成功
scanner = StringScanner.new('foobarbazbatbam') scanner.pos = 6 scanner.exist?(/bat/) # => 6 put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: "foobarbaz" # matched : "bat" # post_match: "bam" # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: ["bat", nil] # []: # [0]: "bat" # [1]: nil put_situation(scanner) # Situation: # pos: 6 # charpos: 6 # rest: "bazbatbam" # rest_size: 9
如果匹配失败
-
返回
nil
。 -
清除所有 [匹配 值]。
scanner.exist?(/nope/) # => nil match_values_cleared?(scanner) # => true
static VALUE strscan_exist_p(VALUE self, VALUE re) { return strscan_do_scan(self, re, 0, 0, 0); }
返回是否设置了 [固定锚点 属性]。
static VALUE strscan_fixed_anchor_p(VALUE self) { struct strscanner *p; p = check_strscan(self); return p->fixed_anchor_p ? Qtrue : Qfalse; }
static VALUE strscan_get_byte(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); CLEAR_MATCH_STATUS(p); if (EOS_P(p)) return Qnil; p->prev = p->curr; p->curr++; MATCHED(p); adjust_registers_to_matched(p); return extract_range(p, adjust_register_position(p, p->regs.beg[0]), adjust_register_position(p, p->regs.end[0])); }
static VALUE strscan_getch(VALUE self) { struct strscanner *p; long len; GET_SCANNER(self, p); CLEAR_MATCH_STATUS(p); if (EOS_P(p)) return Qnil; len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str)); len = minl(len, S_RESTLEN(p)); p->prev = p->curr; p->curr += len; MATCHED(p); adjust_registers_to_matched(p); return extract_range(p, adjust_register_position(p, p->regs.beg[0]), adjust_register_position(p, p->regs.end[0])); }
返回 self
的字符串表示形式,其中可能显示
scanner = StringScanner.new("Fri Dec 12 1975 14:39") scanner.pos = 11 scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
如果在字符串的开头,则省略上面的第 4 项(后续子字符串)
scanner.reset scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
如果在字符串的末尾,则省略上面的所有项
scanner.terminate scanner.inspect # => "#<StringScanner fin>"
static VALUE strscan_inspect(VALUE self) { struct strscanner *p; VALUE a, b; p = check_strscan(self); if (NIL_P(p->str)) { a = rb_sprintf("#<%"PRIsVALUE" (uninitialized)>", rb_obj_class(self)); return a; } if (EOS_P(p)) { a = rb_sprintf("#<%"PRIsVALUE" fin>", rb_obj_class(self)); return a; } if (p->curr == 0) { b = inspect2(p); a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld @ %"PRIsVALUE">", rb_obj_class(self), p->curr, S_LEN(p), b); return a; } a = inspect1(p); b = inspect2(p); a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld %"PRIsVALUE" @ %"PRIsVALUE">", rb_obj_class(self), p->curr, S_LEN(p), a, b); return a; }
尝试在 [目标 子字符串] 的开头 [匹配] 给定的 pattern
;不修改 [位置]。
如果匹配成功
-
设置 [匹配 值]。
-
返回匹配的子字符串的大小(以字节为单位)。
scanner = StringScanner.new('foobarbaz') scanner.pos = 3 scanner.match?(/bar/) => 3 put_match_values(scanner) # Basic match values: # matched?: true # matched_size: 3 # pre_match: "foo" # matched : "bar" # post_match: "baz" # Captured match values: # size: 1 # captures: [] # named_captures: {} # values_at: ["bar", nil] # []: # [0]: "bar" # [1]: nil put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "barbaz" # rest_size: 6
如果匹配失败
-
清除匹配值。
-
返回
nil
。 -
不递增位置。
scanner.match?(/nope/) # => nil match_values_cleared?(scanner) # => true
static VALUE strscan_match_p(VALUE self, VALUE re) { return strscan_do_scan(self, re, 0, 0, 1); }
如果最近的 [匹配] 尝试成功,则返回匹配的子字符串,否则返回 nil
;请参阅 [基本匹配 值]
scanner = StringScanner.new('foobarbaz') scanner.matched # => nil scanner.pos = 3 scanner.match?(/bar/) # => 3 scanner.matched # => "bar" scanner.match?(/nope/) # => nil scanner.matched # => nil
static VALUE strscan_matched(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; return extract_range(p, adjust_register_position(p, p->regs.beg[0]), adjust_register_position(p, p->regs.end[0])); }
如果最近的 [匹配 尝试] 成功,则返回 true
,否则返回 false
;请参阅 [基本匹配 值]
scanner = StringScanner.new('foobarbaz') scanner.matched? # => false scanner.pos = 3 scanner.exist?(/baz/) # => 6 scanner.matched? # => true scanner.exist?(/nope/) # => nil scanner.matched? # => false
static VALUE strscan_matched_p(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); return MATCHED_P(p) ? Qtrue : Qfalse; }
如果最近的匹配 [匹配 尝试] 成功,则返回匹配的子字符串的大小(以字节为单位),否则返回 nil
;请参阅 [基本匹配 值]
scanner = StringScanner.new('foobarbaz') scanner.matched_size # => nil pos = 3 scanner.exist?(/baz/) # => 9 scanner.matched_size # => 3 scanner.exist?(/nope/) # => nil scanner.matched_size # => nil
static VALUE strscan_matched_size(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; return LONG2NUM(p->regs.end[0] - p->regs.beg[0]); }
如果最近的匹配尝试成功,则返回索引为 (1..) 的捕获匹配值数组,否则返回 nil;请参阅 [捕获的匹配 值]
scanner = StringScanner.new('Fri Dec 12 1975 14:39') scanner.named_captures # => {} pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) / scanner.match?(pattern) scanner.named_captures # => {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"} scanner.string = 'nope' scanner.match?(pattern) scanner.named_captures # => {"wday"=>nil, "month"=>nil, "day"=>nil} scanner.match?(/nosuch/) scanner.named_captures # => {}
static VALUE strscan_named_captures(VALUE self) { struct strscanner *p; named_captures_data data; GET_SCANNER(self, p); data.self = self; data.captures = rb_hash_new(); if (!RB_NIL_P(p->regex)) { onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data); } return data.captures; }
返回子字符串 string[pos, length]
;不更新 [匹配 值] 或 [位置]
scanner = StringScanner.new('foobarbaz') scanner.pos = 3 scanner.peek(3) # => "bar" scanner.terminate scanner.peek(3) # => ""
static VALUE strscan_peek(VALUE self, VALUE vlen) { struct strscanner *p; long len; GET_SCANNER(self, p); len = NUM2LONG(vlen); if (EOS_P(p)) return str_new(p, "", 0); len = minl(len, S_RESTLEN(p)); return extract_beg_len(p, p->curr, len); }
查看当前字节并将其作为整数返回。
s = StringScanner.new('ab') s.peek_byte # => 97
static VALUE strscan_peek_byte(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (EOS_P(p)) return Qnil; return INT2FIX((unsigned char)*CURPTR(p)); }
static VALUE strscan_get_pos(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); return INT2FIX(p->curr); }
static VALUE strscan_set_pos(VALUE self, VALUE v) { struct strscanner *p; long i; GET_SCANNER(self, p); i = NUM2INT(v); if (i < 0) i += S_LEN(p); if (i < 0) rb_raise(rb_eRangeError, "index out of range"); if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range"); p->curr = i; return LONG2NUM(i); }
如果最近的匹配尝试成功,则返回匹配的子字符串之后的子字符串,否则返回 nil
;请参阅 [基本匹配 值]
scanner = StringScanner.new('foobarbaz') scanner.post_match # => nil scanner.pos = 3 scanner.match?(/bar/) # => 3 scanner.post_match # => "baz" scanner.match?(/nope/) # => nil scanner.post_match # => nil
static VALUE strscan_post_match(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; return extract_range(p, adjust_register_position(p, p->regs.end[0]), S_LEN(p)); }
如果最近的匹配尝试成功,则返回匹配的子字符串之前的子字符串,否则返回 nil
;请参阅 [基本匹配 值]
scanner = StringScanner.new('foobarbaz') scanner.pre_match # => nil scanner.pos = 3 scanner.exist?(/baz/) # => 6 scanner.pre_match # => "foobar" # Substring of entire string, not just target string. scanner.exist?(/nope/) # => nil scanner.pre_match # => nil
static VALUE strscan_pre_match(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; return extract_range(p, 0, adjust_register_position(p, p->regs.beg[0])); }
将 [字节 位置] 和 [字符 位置] 都设置为零,并清除 [匹配 值];返回 self
scanner = StringScanner.new('foobarbaz') scanner.exist?(/bar/) # => 6 scanner.reset # => #<StringScanner 0/9 @ "fooba..."> put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: "foobarbaz" # rest_size: 9 # => nil match_values_cleared?(scanner) # => true
static VALUE strscan_reset(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); p->curr = 0; CLEAR_MATCH_STATUS(p); return self; }
返回 [存储的 字符串] 的“剩余”部分(当前 [位置] 之后的所有部分),即 [目标 子字符串]
scanner = StringScanner.new('foobarbaz') scanner.rest # => "foobarbaz" scanner.pos = 3 scanner.rest # => "barbaz" scanner.terminate scanner.rest # => ""
static VALUE strscan_rest(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (EOS_P(p)) { return str_new(p, "", 0); } return extract_range(p, p->curr, S_LEN(p)); }
返回 [存储的 字符串] 的 rest
的大小(以字节为单位)
scanner = StringScanner.new('foobarbaz') scanner.rest # => "foobarbaz" scanner.rest_size # => 9 scanner.pos = 3 scanner.rest # => "barbaz" scanner.rest_size # => 6 scanner.terminate scanner.rest # => "" scanner.rest_size # => 0
static VALUE strscan_rest_size(VALUE self) { struct strscanner *p; long i; GET_SCANNER(self, p); if (EOS_P(p)) { return INT2FIX(0); } i = S_RESTLEN(p); return INT2FIX(i); }
static VALUE strscan_scan(VALUE self, VALUE re) { return strscan_do_scan(self, re, 1, 1, 1); }
扫描一个字节并将其作为整数返回。此方法对多字节字符不敏感。另请参阅:getch
。
static VALUE strscan_scan_byte(VALUE self) { struct strscanner *p; VALUE byte; GET_SCANNER(self, p); CLEAR_MATCH_STATUS(p); if (EOS_P(p)) return Qnil; byte = INT2FIX((unsigned char)*CURPTR(p)); p->prev = p->curr; p->curr++; MATCHED(p); adjust_registers_to_matched(p); return byte; }
如果未提供“base”或“base”为“10”,则等效于使用“ [+-]?d+”模式调用“#scan”,并返回 Integer 或 nil。
如果“base”为“16”,则等效于使用“ [+-]?(0x)?+”模式调用“#scan”,并返回 Integer 或 nil。
扫描的字符串必须使用与 ASCII 兼容的编码进行编码,否则将引发 Encoding::CompatibilityError。
# File strscan/lib/strscan/strscan.rb, line 15 def scan_integer(base: 10) case base when 10 scan_base10_integer when 16 scan_base16_integer else raise ArgumentError, "Unsupported integer base: #{base.inspect}, expected 10 or 16" end end
static VALUE strscan_scan_until(VALUE self, VALUE re) { return strscan_do_scan(self, re, 1, 1, 0); }
如果最近的匹配尝试成功,则返回捕获计数,否则返回 nil
;请参阅 [捕获匹配 值]
scanner = StringScanner.new('Fri Dec 12 1975 14:39') scanner.size # => nil pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) / scanner.match?(pattern) scanner.values_at(*0..scanner.size) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil] scanner.size # => 4 scanner.match?(/nope/) # => nil scanner.size # => nil
static VALUE strscan_size(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; return INT2FIX(p->regs.num_regs); }
static VALUE strscan_skip(VALUE self, VALUE re) { return strscan_do_scan(self, re, 1, 0, 1); }
static VALUE strscan_skip_until(VALUE self, VALUE re) { return strscan_do_scan(self, re, 1, 0, 0); }
返回 [存储的 字符串]
scanner = StringScanner.new('foobar') scanner.string # => "foobar" scanner.concat('baz') scanner.string # => "foobarbaz"
static VALUE strscan_get_string(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); return p->str; }
将 [存储的 字符串] 替换为给定的 other_string
scanner = StringScanner.new('foobar') scanner.scan(/foo/) put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "bar" # rest_size: 3 match_values_cleared?(scanner) # => false scanner.string = 'baz' # => "baz" put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: "baz" # rest_size: 3 match_values_cleared?(scanner) # => true
static VALUE strscan_set_string(VALUE self, VALUE str) { struct strscanner *p = check_strscan(self); StringValue(str); p->str = str; p->curr = 0; CLEAR_MATCH_STATUS(p); return str; }
static VALUE strscan_terminate(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); p->curr = S_LEN(p); CLEAR_MATCH_STATUS(p); return self; }
scanner = StringScanner.new('foobarbaz') scanner.scan(/foo/) put_situation(scanner) # Situation: # pos: 3 # charpos: 3 # rest: "barbaz" # rest_size: 6 scanner.unscan # => #<StringScanner 0/9 @ "fooba..."> put_situation(scanner) # Situation: # pos: 0 # charpos: 0 # rest: "foobarbaz" # rest_size: 9
如果匹配值被清除,则引发异常
scanner.scan(/nope/) # => nil match_values_cleared?(scanner) # => true scanner.unscan # Raises StringScanner::Error.
static VALUE strscan_unscan(VALUE self) { struct strscanner *p; GET_SCANNER(self, p); if (! MATCHED_P(p)) rb_raise(ScanError, "unscan failed: previous match record not exist"); p->curr = p->prev; CLEAR_MATCH_STATUS(p); return self; }
返回捕获的子字符串数组,如果没有则返回 nil
。
对于每个 specifier
,返回的子字符串为 [specifier]
;请参阅 []
。
scanner = StringScanner.new('Fri Dec 12 1975 14:39') pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) / scanner.match?(pattern) scanner.values_at(*0..3) # => ["Fri Dec 12 ", "Fri", "Dec", "12"] scanner.values_at(*%i[wday month day]) # => ["Fri", "Dec", "12"]
static VALUE strscan_values_at(int argc, VALUE *argv, VALUE self) { struct strscanner *p; long i; VALUE new_ary; GET_SCANNER(self, p); if (! MATCHED_P(p)) return Qnil; new_ary = rb_ary_new2(argc); for (i = 0; i<argc; i++) { rb_ary_push(new_ary, strscan_aref(self, argv[i])); } return new_ary; }
私有实例方法
返回 self
的浅拷贝;副本中的 [存储的 字符串] 与 self
中的字符串相同。
static VALUE strscan_init_copy(VALUE vself, VALUE vorig) { struct strscanner *self, *orig; self = check_strscan(vself); orig = check_strscan(vorig); if (self != orig) { self->flags = orig->flags; self->str = orig->str; self->prev = orig->prev; self->curr = orig->curr; if (rb_reg_region_copy(&self->regs, &orig->regs)) rb_memerror(); RB_GC_GUARD(vorig); } return vself; }
static VALUE strscan_scan_base10_integer(VALUE self) { char *ptr; long len = 0; struct strscanner *p; GET_SCANNER(self, p); CLEAR_MATCH_STATUS(p); strscan_must_ascii_compat(p->str); ptr = CURPTR(p); long remaining_len = S_RESTLEN(p); if (remaining_len <= 0) { return Qnil; } if (ptr[len] == '-' || ptr[len] == '+') { len++; } if (!rb_isdigit(ptr[len])) { return Qnil; } MATCHED(p); p->prev = p->curr; while (len < remaining_len && rb_isdigit(ptr[len])) { len++; } return strscan_parse_integer(p, 10, len); }
static VALUE strscan_scan_base16_integer(VALUE self) { char *ptr; long len = 0; struct strscanner *p; GET_SCANNER(self, p); CLEAR_MATCH_STATUS(p); strscan_must_ascii_compat(p->str); ptr = CURPTR(p); long remaining_len = S_RESTLEN(p); if (remaining_len <= 0) { return Qnil; } if (ptr[len] == '-' || ptr[len] == '+') { len++; } if ((remaining_len >= (len + 2)) && ptr[len] == '0' && ptr[len + 1] == 'x') { len += 2; } if (len >= remaining_len || !rb_isxdigit(ptr[len])) { return Qnil; } MATCHED(p); p->prev = p->curr; while (len < remaining_len && rb_isxdigit(ptr[len])) { len++; } return strscan_parse_integer(p, 16, len); }