класс StringScanner
StringScanner предоставляет операции лексического сканирования над String. Вот пример его использования:
s = StringScanner.new('This is an example string')
s.eos? # -> false
p s.scan(/\w+/) # -> "This"
p s.scan(/\w+/) # -> nil
p s.scan(/\s+/) # -> " "
p s.scan(/\s+/) # -> nil
p s.scan(/\w+/) # -> "is"
s.eos? # -> false
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "an"
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "example"
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "string"
s.eos? # -> true
p s.scan(/\s+/) # -> nil
p s.scan(/\w+/) # -> nil
Сканирование строки подразумевает запоминание положения указателя сканирования, который представляет собой просто индекс. Цель сканирования — перемещаться вперёд понемногу, поэтому соответствия ищутся после указателя сканирования; обычно сразу после него.
Для строки “test string” следующие позиции указателя сканирования:
t e s t s t r i n g
0 1 2 ... 1
0 Когда вы scan шаблон (регулярное выражение), соответствие должно начинаться с символа после указателя сканирования. Если вы используете scan_until, то соответствие может начинаться где угодно после указателя сканирования. В обоих случаях указатель сканирования перемещается непосредственно за последним символом соответствия, готовым к сканированию следующего символа. Это демонстрируется примером выше.
Method Категории
Помимо простых сканеров, существуют и другие методы. Вы можете заглядывать вперёд в строку, не сканируя её фактически. Вы можете получить последнее совпадение. Вы можете изменить строку, которую сканирует, сбросить или прекратить сканирование, узнать или изменить позицию указателя сканирования, перейти дальше и так далее.
Перемещение указателя сканирования
Предварительный просмотр
Определение текущей позиции
-
beginning_of_line?(начало строки?)
Указание текущей позиции
Данные о совпадении
Разное
Для нескольких методов существуют псевдонимы.
Методы публичного класса
static VALUE
strscan_s_mustc(VALUE self)
{
return self;
} Этот метод определён для обратной совместимости.
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;
} Создаёт новый объект StringScanner для сканирования указанной string.
Если fixed_anchor равно true, то \A всегда соответствует началу строки. В противном случае, \A всегда соответствует текущей позиции.
Аргумент dup устарел и сейчас не используется.
Общедоступные методы экземпляров
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;
} Добавляет str к строке, которая сканируется. Этот метод не влияет на указатель сканирования.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/Fri /)
s << " +1000 GMT"
s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
s.scan(/Dec/) # -> "Dec"
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 (!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]));
} Возвращает n-ю подгруппу в последнем совпадении.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
s[0] # -> "Fri Dec 12 "
s[1] # -> "Fri"
s[2] # -> "Dec"
s[3] # -> "12"
s.post_match # -> "1975 14:39"
s.pre_match # -> ""
s.reset
s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 "
s[0] # -> "Fri Dec 12 "
s[1] # -> "Fri"
s[2] # -> "Dec"
s[3] # -> "12"
s[:wday] # -> "Fri"
s[:month] # -> "Dec"
s[:day] # -> "12"
s.post_match # -> "1975 14:39"
s.pre_match # -> ""
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;
} Возвращает true тогда и только тогда, когда указатель сканирования находится в начале строки.
s = StringScanner.new("test\ntest\n")
s.bol? # => true
s.scan(/te/)
s.bol? # => false
s.scan(/st\n/)
s.bol? # => true
s.terminate
s.bol? # => true
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 = 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;
} Возвращает подгруппы в последнем совпадении (без учета полного совпадения). Если ничего не было сопоставлено ранее, возвращает nil.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
s.captures # -> ["Fri", "Dec", "12"]
s.scan(/(\w+) (\w+) (\d+) /) # -> nil
s.captures # -> nil
static VALUE
strscan_get_charpos(VALUE self)
{
struct strscanner *p;
VALUE substr;
GET_SCANNER(self, p);
substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), INT2NUM(p->curr));
return rb_str_length(substr);
} Возвращает позицию символа указателя сканирования. В позиции «сброс» это значение равно нулю. В позиции «прекращение» (т. е. строка исчерпана) это значение равно размеру строки.
Короче говоря, это индекс в строке с нулевым началом.
s = StringScanner.new("abcädeföghi")
s.charpos # -> 0
s.scan_until(/ä/) # -> "abcä"
s.pos # -> 5
s.charpos # -> 4
static VALUE
strscan_check(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 1, 1);
} Возвращает значение, которое scan вернул бы, без продвижения указателя сканирования. Регистр совпадений, однако, затронут.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.check /Fri/ # -> "Fri"
s.pos # -> 0
s.matched # -> "Fri"
s.check /12/ # -> nil
s.matched # -> nil
Мнемоника: он «проверяет», вернёт ли scan значение.
static VALUE
strscan_check_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 1, 0);
} Возвращает значение, которое scan_until вернул бы, без продвижения указателя сканирования. Регистр совпадений, однако, затронут.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.check_until /12/ # -> "Fri Dec 12"
s.pos # -> 0
s.matched # -> 12
Мнемоника: он «проверяет», вернёт ли scan_until значение.
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;
} Добавляет str к строке, которая сканируется. Этот метод не влияет на указатель сканирования.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/Fri /)
s << " +1000 GMT"
s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
s.scan(/Dec/) # -> "Dec"
static VALUE
strscan_eos_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return EOS_P(p) ? Qtrue : Qfalse;
} Возвращает true если указатель сканирования находится в конце строки.
s = StringScanner.new('test string')
p s.eos? # => false
s.scan(/test/)
p s.eos? # => false
s.terminate
p s.eos? # => true
static VALUE
strscan_exist_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 0);
} Предварительно проверяет, существует ли pattern где-либо в строке, без продвижения указателя сканирования. Это позволяет предсказать, вернёт ли scan_until значение.
s = StringScanner.new('test string')
s.exist? /s/ # -> 3
s.scan /test/ # -> "test"
s.exist? /s/ # -> 2
s.exist? /e/ # -> nil
static VALUE
strscan_fixed_anchor_p(VALUE self)
{
struct strscanner *p;
p = check_strscan(self);
return p->fixed_anchor_p ? Qtrue : Qfalse;
} Использует ли scanner режим фиксированного якоря или нет.
Если используется режим фиксированного якоря, \A всегда соответствует началу строки. В противном случае, \A всегда соответствует текущей позиции.
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]));
} Сканирует один байт и возвращает его. Этот метод не чувствителен к многобайтовым символам. См. также: getch.
s = StringScanner.new('ab')
s.get_byte # => "a"
s.get_byte # => "b"
s.get_byte # => nil
$KCODE = 'EUC'
s = StringScanner.new("\244\242")
s.get_byte # => "\244"
s.get_byte # => "\242"
s.get_byte # => nil
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]));
} Сканирует один символ и возвращает его. Этот метод чувствителен к многобайтовым символам.
s = StringScanner.new("ab")
s.getch # => "a"
s.getch # => "b"
s.getch # => nil
$KCODE = 'EUC'
s = StringScanner.new("\244\242")
s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP
s.getch # => nil
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;
} Возвращает строку, представляющую объект StringScanner, показывая:
-
текущую позицию
-
размер строки
-
символы, окружающие указатель сканирования
s =
StringScanner.new(“Fri Dec 12 1975 14:39”) s.inspect # -> '#<StringScanner 0/21 @ “Fri D…”>' s.scan_until /12/ # -> “Fri Dec 12” s.inspect # -> '#<StringScanner 10/21 “…ec 12” @ “ 1975…”>'
static VALUE
strscan_match_p(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 0, 0, 1);
} Проверяет, соответствует ли заданный pattern с текущего указателя сканирования. Возвращает длину совпадения или nil. Указатель сканирования не сдвигается.
s = StringScanner.new('test string')
p s.match?(/\w+/) # -> 4
p s.match?(/\w+/) # -> 4
p s.match?("test") # -> 4
p s.match?(/\s+/) # -> 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]));
} Возвращает последнюю сопоставленную строку.
s = StringScanner.new('test string')
s.match?(/\w+/) # -> 4
s.matched # -> "test"
static VALUE
strscan_matched_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return MATCHED_P(p) ? Qtrue : Qfalse;
} Возвращает true если последнее совпадение было успешным.
s = StringScanner.new('test string')
s.match?(/\w+/) # => 4
s.matched? # => true
s.match?(/\d+/) # => nil
s.matched? # => false
static VALUE
strscan_matched_size(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
} Возвращает размер последнего совпадения (см. matched) или nil если не было последнего совпадения.
s = StringScanner.new('test string')
s.check /\w+/ # -> "test"
s.matched_size # -> 4
s.check /\d+/ # -> nil
s.matched_size # -> nil
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);
} Извлекает строку, соответствующую string[pos,len], без продвижения указателя сканирования.
s = StringScanner.new('test string')
s.peek(7) # => "test st"
s.peek(7) # => "test st"
static VALUE
strscan_get_pos(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return INT2FIX(p->curr);
} Возвращает байтовую позицию указателя сканирования. В позиции «сброс» это значение равно нулю. В позиции «завершение» (т. е. строка исчерпана) это значение равно размеру строки в байтах.
Короче говоря, это индекс в байтах строки, начинающийся с 0.
s = StringScanner.new('test string')
s.pos # -> 0
s.scan_until /str/ # -> "test str"
s.pos # -> 8
s.terminate # -> #<StringScanner fin>
s.pos # -> 11
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 INT2NUM(i);
} Устанавливает байтовую позицию указателя сканирования.
s = StringScanner.new('test string')
s.pos = 7 # -> 7
s.rest # -> "ring"
static VALUE
strscan_get_pos(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return INT2FIX(p->curr);
} Возвращает байтовую позицию указателя сканирования. В позиции «сброс» это значение равно нулю. В позиции «завершение» (т. е. строка исчерпана) это значение равно размеру строки в байтах.
Короче говоря, это индекс в байтах строки, начинающийся с 0.
s = StringScanner.new('test string')
s.pos # -> 0
s.scan_until /str/ # -> "test str"
s.pos # -> 8
s.terminate # -> #<StringScanner fin>
s.pos # -> 11
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 INT2NUM(i);
} Устанавливает байтовую позицию указателя сканирования.
s = StringScanner.new('test string')
s.pos = 7 # -> 7
s.rest # -> "ring"
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));
} Возвращает после-совпадение (в смысле регулярных выражений) последнего сканирования.
s = StringScanner.new('test string')
s.scan(/\w+/) # -> "test"
s.scan(/\s+/) # -> " "
s.pre_match # -> "test"
s.post_match # -> "string"
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]));
} Возвращает до-совпадение (в смысле регулярных выражений) последнего сканирования.
s = StringScanner.new('test string')
s.scan(/\w+/) # -> "test"
s.scan(/\s+/) # -> " "
s.pre_match # -> "test"
s.post_match # -> "string"
static VALUE
strscan_reset(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
p->curr = 0;
CLEAR_MATCH_STATUS(p);
return self;
} Сбрасывает указатель сканирования (индекс 0) и очищает данные совпадения.
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));
} Возвращает «остаток» строки (т. е. всё после указателя сканирования). Если больше данных нет (eos? = true), возвращает "".
static VALUE
strscan_rest_p(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return EOS_P(p) ? Qfalse : Qtrue;
} Возвращает true, если в строке есть дополнительные данные. См. eos?. Этот метод устарел; используйте eos? вместо него.
s = StringScanner.new('test string')
s.eos? # These two
s.rest? # are opposites.
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);
} s.rest_size эквивалентно s.rest.size.
static VALUE
strscan_restsize(VALUE self)
{
rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
return strscan_rest_size(self);
} s.restsize эквивалентно s.rest_size. Этот метод устарел; используйте rest_size вместо него.
static VALUE
strscan_scan(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 1, 1);
} Попытка сопоставления с pattern в текущей позиции. Если совпадение есть, сканер продвигает «указатель сканирования» и возвращает совпавшую строку. В противном случае, сканер возвращает nil.
s = StringScanner.new('test string')
p s.scan(/\w+/) # -> "test"
p s.scan(/\w+/) # -> nil
p s.scan(/\s+/) # -> " "
p s.scan("str") # -> "str"
p s.scan(/\w+/) # -> "ing"
p s.scan(/./) # -> nil
static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
} Проверяет, соответствует ли данное pattern с текущего указателя сканирования. Продвигает указатель сканирования, если advance_pointer_p равно true. Возвращает совпавшую строку, если return_string_p равно true. Регистр совпадений изменяется.
«полный» означает «#scan со всеми параметрами».
static VALUE
strscan_scan_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 1, 0);
} Сканирует строку до совпадения с pattern. Возвращает подстроку до конца совпадения, продвигая указатель сканирования до этой позиции. Если совпадения нет, возвращает nil.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan_until(/1/) # -> "Fri Dec 1"
s.pre_match # -> "Fri Dec "
s.scan_until(/XYZ/) # -> nil
static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
} Сканирует строку до совпадения с pattern. Продвигает указатель сканирования, если advance_pointer_p, иначе нет. Возвращает совпавшую строку, если return_string_p равно true, иначе возвращает количество продвинутых байт. Данный метод влияет на регистр совпадений.
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);
} Возвращает количество подгрупп в последнем совпадении. Полное совпадение учитывается как подгруппа.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
s.size # -> 4
static VALUE
strscan_skip(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 0, 1);
} Попытка перескочить через данное pattern, начиная с указателя сканирования. Если совпадение есть, указатель сканирования продвинется до конца совпадения, и возвращается длина совпадения. В противном случае, возвращается nil.
Аналогично scan, но без возврата совпавшей строки.
s = StringScanner.new('test string')
p s.skip(/\w+/) # -> 4
p s.skip(/\w+/) # -> nil
p s.skip(/\s+/) # -> 1
p s.skip("st") # -> 2
p s.skip(/\w+/) # -> 4
p s.skip(/./) # -> nil
static VALUE
strscan_skip_until(VALUE self, VALUE re)
{
return strscan_do_scan(self, re, 1, 0, 0);
} Продвигает указатель сканирования до тех пор, пока не будет найдено и прочитано совпадение с pattern. Возвращает количество продвинутых байт, или nil в случае отсутствия совпадения.
Ищет совпадение с pattern, и продвигает указатель сканирования до конца совпадения. Возвращает количество пропущенных символов, или nil если совпадение не найдено.
Аналогично scan_until, но без возврата промежуточной строки.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.skip_until /12/ # -> 10
s #
static VALUE
strscan_get_string(VALUE self)
{
struct strscanner *p;
GET_SCANNER(self, p);
return p->str;
} Возвращает сканируемую строку.
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;
} Изменяет строку, сканируемую сканером, на str и сбрасывает сканер. Возвращает 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;
} Устанавливает указатель сканирования в конец строки и очищает сопоставленные данные.
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;
} Устанавливает указатель сканирования в предыдущую позицию. Запоминается только одна предыдущая позиция, и она изменяется при каждой операции сканирования.
s = StringScanner.new('test string')
s.scan(/\w+/) # => "test"
s.unscan
s.scan(/../) # => "te"
s.scan(/\d/) # => nil
s.unscan # ScanError: unscan failed: previous match record not exist
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;
} Возвращает подгруппы в последнем сопоставлении по заданным индексам. Если ранее ничего не сопоставлялось, возвращает nil.
s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
s.values_at 0, -1, 5, 2 # -> ["Fri Dec 12 ", "12", nil, "Dec"]
s.scan(/(\w+) (\w+) (\d+) /) # -> nil
s.values_at 0, -1, 5, 2 # -> nil
Приватные методы экземпляра
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;
} Создаёт копию объекта StringScanner.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.