Spec-Zone.ru › Ruby 3.2

класс StringScanner

Родитель:
Объект

StringScanner предоставляет возможности лексического сканирования строки String. Вот пример его использования:

require 'strscan'

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 Категории методов

Помимо простых сканеров, существуют и другие методы. Вы можете просматривать строку вперёд, не фактически сканируя её. Вы можете получить последнее найденное соответствие. Вы можете изменить сканируемую строку, сбросить или остановить сканер, узнать или изменить позицию указателя сканирования, пропустить вперёд и так далее.

Перемещение указателя сканирования

  • getch

  • get_byte

  • scan

  • scan_until

  • skip

  • skip_until

Предварительный просмотр

  • check

  • check_until

  • exist?

  • match?

  • peek

Определение текущей позиции

  • beginning_of_line? (#bol?)

  • eos?

  • rest?

  • rest_size

  • pos

Установка позиции

  • reset

  • terminate

  • pos=

Данные соответствия

  • matched

  • matched?

  • matched_size

  • #[]

  • pre_match

  • post_match

Разное

  • <<

  • concat

  • string

  • string=

  • unscan

Существуют псевдонимы для некоторых методов.

Методы публичного класса

must_C_version Показать исходный код
static VALUE
strscan_s_mustc(VALUE self)
{
    return self;
}

Этот метод определён для обратной совместимости.

new(string, fixed_anchor: false) Показать исходный код
new(string, dup = false)
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 устарел и сейчас не используется.

Методы публичного экземпляра

<<(str)

Добавляет 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"
Псевдоним для: concat
[](n) Показать исходный код
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]));
}

Возвращает 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                        # -> ""
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;
}

Возвращает 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
captures Показать исходный код
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
charpos() Показать исходный код
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)));
}

Возвращает позицию символа указателя сканирования. В позиции «сброса» это значение равно нулю. В позиции «остановки» (т. е. строка исчерпана) это значение равно размеру строки.

Короче говоря, это индекс в строке с нуля.

s = StringScanner.new("abc\u00e4def\u00f6ghi")
s.charpos                # -> 0
s.scan_until(/\u00e4/)   # -> "abc\u00E4"
s.pos                    # -> 5
s.charpos                # -> 4
check(pattern) Показать исходный код
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 значение.

check_until(pattern) Показать исходный код
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 значение.

clear() Показать исходный код
static VALUE
strscan_clear(VALUE self)
{
    rb_warning("StringScanner#clear is obsolete; use #terminate instead");
    return strscan_terminate(self);
}

Эквивалентно terminate. Этот метод устарел; используйте terminate вместо него.

concat(str) Показать исходный код
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"
Также алиас для: <<
empty?() Показать исходный код
static VALUE
strscan_empty_p(VALUE self)
{
    rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
    return strscan_eos_p(self);
}

Эквивалентно eos?. Этот метод устарел; используйте eos? вместо него.

eos?() Показать исходный код
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
exist?(pattern) Показать исходный код
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
fixed_anchor? → true или false Показать исходный код
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 всегда соответствует текущей позиции.

get_byte() Показать исходный код
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

s = StringScanner.new("\244\242".force_encoding("euc-jp"))
s.get_byte         # => "\xA4"
s.get_byte         # => "\xA2"
s.get_byte         # => nil
getbyte() Показать исходный код
static VALUE
strscan_getbyte(VALUE self)
{
    rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
    return strscan_get_byte(self);
}

Эквивалентно get_byte. Этот метод устарел; используйте get_byte вместо него.

getch() Показать исходный код
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

s = StringScanner.new("\244\242".force_encoding("euc-jp"))
s.getch           # => "\x{A4A2}"   # Japanese hira-kana "A" in EUC-JP
s.getch           # => nil
inspect() Показать исходный код
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(“Пт Дек 12 1975 14:39”) s.inspect # -> ‘#<StringScanner 0/21 @ “Пт D…”>’ s.scan_until /12/ # -> “Пт Дек 12” s.inspect # -> ‘#<StringScanner 10/21 “…ек 12” @ “ 1975…”>’

match?(pattern) Показать исходный код
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
matched() Показать исходный код
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"
matched?() Показать исходный код
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
matched_size() Показать исходный код
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]);
}

Возвращает размер последнего совпадения в байтах или nil если не было недавнего совпадения. Это отличается от matched.size, который вернет размер в символах.

s = StringScanner.new('test string')
s.check /\w+/           # -> "test"
s.matched_size          # -> 4
s.check /\d+/           # -> nil
s.matched_size          # -> nil
named_captures → hash Показать исходный код
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();
    onig_foreach_name(RREGEXP_PTR(p->regex), named_captures_iter, &data);

    return data.captures;
}

Возвращает хэш строковых переменных, соответствующих регулярному выражению.

scan = StringScanner.new('foobarbaz')
scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}
peek(len) Показать исходный код
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"
peep(p1) Показать исходный код
static VALUE
strscan_peep(VALUE self, VALUE vlen)
{
    rb_warning("StringScanner#peep is obsolete; use #peek instead");
    return strscan_peek(self, vlen);
}

Эквивалентно peek. Этот метод устарел; используйте peek вместо него.

pointer()

Возвращает позицию байта указателя сканирования. В позиции «сброс» это значение равно нулю. В позиции «завершено» (т. е. строка исчерпана), это значение равно размеру строки в байтах.

Короче говоря, это индекс, начинающийся с 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
Псевдоним для: pos
pointer=(p1)

Устанавливает позицию байта указателя сканирования.

s = StringScanner.new('test string')
s.pos = 7            # -> 7
s.rest               # -> "ring"
Псевдоним для: pos=
pos() Показать исходный код
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
Также является псевдонимом для: pointer
pos=(n) Показать исходный код
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);
}

Устанавливает позицию байта указателя сканирования.

s = StringScanner.new('test string')
s.pos = 7            # -> 7
s.rest               # -> "ring"
Также является псевдонимом для: pointer=
post_match() Показать исходный код
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"
pre_match() Показать исходный код
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"
reset() Показать исходный код
static VALUE
strscan_reset(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    p->curr = 0;
    CLEAR_MATCH_STATUS(p);
    return self;
}

Сбрасывает указатель сканирования (индекс 0) и очищает данные сопоставления.

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));
}

Возвращает «остаток» строки (т. е. все после указателя сканирования). Если больше нет данных (eos? = true), возвращает "".

rest?() Показать исходный код
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.
rest_size() Показать исходный код
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.

restsize() Показать исходный код
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 вместо него.

scan(pattern) → String Показать исходный код
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
scan_full(pattern, advance_pointer_p, return_string_p) Показать исходный код
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 истинно. Возвращает совпадающую строку, если return_string_p истинно. Регистр сопоставления затронут.

«Полный» означает «#scan с полными параметрами».

scan_until(pattern) Показать исходный код
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
search_full(pattern, advance_pointer_p, return_string_p) Показать исходный код
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 истинно, иначе возвращает количество продвинутых байтов. Этот метод влияет на регистр сопоставления.

size Показать исходный код
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
skip(pattern) Показать исходный код
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
skip_until(pattern) Показать исходный код
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                           #
string() Показать исходный код
static VALUE
strscan_get_string(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return p->str;
}

Возвращает сканируемую строку.

string=(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.

terminate Показать исходный код
clear
static VALUE
strscan_terminate(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    p->curr = S_LEN(p);
    CLEAR_MATCH_STATUS(p);
    return self;
}

Устанавливает указатель сканирования в конец строки и очищает сопоставленные данные.

unscan() Показать исходный код
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
values_at( i1, i2, ... iN ) → an_array Показать исходный код
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

Приватные методы экземпляра

dup Показать исходный код
clone
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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API