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;
}
Returns a new StringScanner
object whose [stored string] is the given string
; sets the [fixed-anchor property]:
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_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]));
}
Returns a captured substring or nil
; see [Captured Match Values].
When there are captures:
scanner = StringScanner.new('Fri Dec 12 1975 14:39') scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
-
specifier
zero: returns the entire matched substring:scanner[0] # => "Fri Dec 12 " scanner.pre_match # => "" scanner.post_match # => "1975 14:39"
-
specifier
positive integer. returns then
th capture, ornil
if out of range:scanner[1] # => "Fri" scanner[2] # => "Dec" scanner[3] # => "12" scanner[4] # => nil
-
specifier
negative integer. counts backward from the last subgroup:scanner[-1] # => "12" scanner[-4] # => "Fri Dec 12 " scanner[-5] # => nil
-
specifier
symbol or string. returns the named subgroup, ornil
if no such:scanner[:wday] # => "Fri" scanner['wday'] # => "Fri" scanner[:month] # => "Dec" scanner[:day] # => "12" scanner[:nope] # => nil
When there are no captures, only [0]
returns non-nil
:
scanner = StringScanner.new('foobarbaz') scanner.exist?(/bar/) scanner[0] # => "bar" scanner[1] # => nil
For a failed match, even [0]
returns nil
:
scanner.scan(/nope/) # => nil scanner[0] # => nil scanner[1] # => nil
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;
}
Returns whether the [position] is at the beginning of a line; that is, at the beginning of the [stored string] or immediately after a newline:
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? is an alias for StringScanner#beginning_of_line?
.
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;
}
Returns the array of [captured match values] at indexes (1..)
if the most recent match attempt succeeded, or nil
otherwise:
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_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)));
}
static VALUE
strscan_check(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 1, 1);
}
Attempts to [match] the given pattern
at the beginning of the [target substring]; does not modify the [positions].
If the match succeeds:
-
Returns the matched substring.
-
Sets all [match values].
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
If the match fails:
-
Returns
nil
. -
Clears all [match values].
scanner.check(/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);
}
Attempts to [match] the given pattern
anywhere (at any [position]) in the [target substring]; does not modify the [positions].
If the match succeeds:
-
Sets all [match values].
-
Returns the matched substring, which extends from the current [position] to the end of the matched substring.
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
If the match fails:
-
Clears all [match values].
-
Returns
nil
.
scanner.check_until(/nope/) # => nil match_values_cleared?(scanner) # => true
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;
}
-
Appends the given
more_string
to the [stored string]. -
Returns
self
. -
Does not affect the [positions] or [match values].
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_eos_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return EOS_P(p) ? Qtrue : Qfalse;
}
static VALUE
strscan_exist_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 0);
}
Attempts to [match] the given pattern
anywhere (at any [position]) n the [target substring]; does not modify the [positions].
If the match succeeds:
-
Returns a byte offset: the distance in bytes between the current [position] and the end of the matched substring.
-
Sets all [match values].
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
If the match fails:
-
Returns
nil
. -
Clears all [match values].
scanner.exist?(/nope/) # => nil match_values_cleared?(scanner) # => true
static VALUE
strscan_fixed_anchor_p(VALUE self)
{
struct strscanner *p;
p = check_strscan(self);
return p->fixed_anchor_p ? Qtrue : Qfalse;
}
Returns whether the [fixed-anchor property] is set.
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]));
}
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;
}
Returns a shallow copy of self
; the [stored string] in the copy is the same string as in self
.
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;
}
Returns a string representation of self
that may show:
-
The current [position].
-
The size (in bytes) of the [stored string].
-
The substring preceding the current position.
-
The substring following the current position (which is also the [target substring]).
scanner = StringScanner.new("Fri Dec 12 1975 14:39") scanner.pos = 11 scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
If at beginning-of-string, item 4 above (following substring) is omitted:
scanner.reset scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
If at end-of-string, all items above are omitted:
scanner.terminate scanner.inspect # => "#<StringScanner fin>"
static VALUE
strscan_match_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 1);
}
Attempts to [match] the given pattern
at the beginning of the [target substring]; does not modify the [positions].
If the match succeeds:
-
Sets [match values].
-
Returns the size in bytes of the matched substring.
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
If the match fails:
-
Clears match values.
-
Returns
nil
. -
Does not increment positions.
scanner.match?(/nope/) # => nil match_values_cleared?(scanner) # => true
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]));
}
Returns the matched substring from the most recent [match] attempt if it was successful, or nil
otherwise; see [Basic Matched Values]:
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_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return MATCHED_P(p) ? Qtrue : Qfalse;
}
Returns true
of the most recent [match attempt] was successful, false
otherwise; see [Basic Matched Values]:
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_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]);
}
Returns the size (in bytes) of the matched substring from the most recent match [match attempt] if it was successful, or nil
otherwise; see [Basic Matched Values]:
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_named_captures(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
named_captures_data data;
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;
}
Returns the array of captured match values at indexes (1..) if the most recent match attempt succeeded, or nil otherwise; see [Captured Match Values]:
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_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);
}
Returns the substring string[pos, length]
; does not update [match values] or [positions]:
scanner = StringScanner.new('foobarbaz') scanner.pos = 3 scanner.peek(3) # => "bar" scanner.terminate scanner.peek(3) # => ""
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));
}
Peeks at the current byte and returns it as an integer.
s = StringScanner.new('ab') s.peek_byte # => 97
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);
}
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));
}
Returns the substring that follows the matched substring from the most recent match attempt if it was successful, or nil
otherwise; see [Basic Match Values]:
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_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]));
}
Returns the substring that precedes the matched substring from the most recent match attempt if it was successful, or nil
otherwise; see [Basic Match Values]:
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_reset(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
p->curr = 0;
CLEAR_MATCH_STATUS(p);
return self;
}
Sets both [byte position] and [character position] to zero, and clears [match values]; returns 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_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));
}
Returns the ‘rest’ of the [stored string] (all after the current [position]), which is the [target substring]:
scanner = StringScanner.new('foobarbaz') scanner.rest # => "foobarbaz" scanner.pos = 3 scanner.rest # => "barbaz" scanner.terminate scanner.rest # => ""
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);
}
static VALUE
strscan_scan_byte(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
if (EOS_P(p))
return Qnil;
VALUE byte = INT2FIX((unsigned char)*CURPTR(p));
p->prev = p->curr;
p->curr++;
MATCHED(p);
adjust_registers_to_matched(p);
return byte;
}
Scans one byte and returns it as an integer. This method is not multibyte character sensitive. See also: getch
.
static VALUE
strscan_scan_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 1, 0);
}
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);
}
Returns the count of captures if the most recent match attempt succeeded, nil
otherwise; see [Captures Match Values]:
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_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);
}
static VALUE
strscan_get_string(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return p->str;
}
Returns the [stored string]:
scanner = StringScanner.new('foobar') scanner.string # => "foobar" scanner.concat('baz') scanner.string # => "foobarbaz"
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;
}
Replaces the [stored string] with the given other_string
:
-
Sets both [positions] to zero.
-
Clears [match values].
-
Returns
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_terminate(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
p->curr = S_LEN(p);
CLEAR_MATCH_STATUS(p);
return self;
}
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;
}
Sets the [position] to its value previous to the recent successful [match] attempt:
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
Raises an exception if match values are clear:
scanner.scan(/nope/) # => nil match_values_cleared?(scanner) # => true scanner.unscan # Raises StringScanner::Error.
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;
}
Returns an array of captured substrings, or nil
of none.
For each specifier
, the returned substring is [specifier]
; see []
.
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"]