類別 StringScanner

StringScanner 提供字串的詞法掃描操作。以下是其使用範例

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,則比對可以在掃描指標之後的任何位置發生。這兩種情況下,掃描指標都會移動到比對的最後一個字元之後,準備從下一個字元開始再次掃描。上方範例示範了這一點。

方法類別

除了純粹的掃描器之外,還有其他方法。您可以在不實際掃描的情況下向前查看字串。您可以存取最近的比對。您可以修改正在掃描的字串、重設或終止掃描器、找出或變更掃描指標的位置、向前跳過等。

推進掃描指標

向前搜尋

尋找我們所在的位置

設定我們所在的位置

比對資料

其他

有幾個方法有別名。

公開類別方法

must_C_version 按一下以切換原始碼

此方法定義於向後相容性。

static VALUE
strscan_s_mustc(VALUE self)
{
    return self;
}
new(string, fixed_anchor: false) 按一下以切換原始碼
new(string, dup = false)

建立一個新的 StringScanner 物件,以掃描給定的 string

如果 fixed_anchortrue\A 永遠比對字串的開頭。否則,\A 永遠比對目前的位置。

dup 參數已過時,現在不使用了。

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

公開實例方法

<<(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) 按一下以切換原始碼

傳回最近一次比對的第 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_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]));
}
beginning_of_line?() 按一下以切換原始碼

僅當掃描指標在行首時,傳回 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_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;
}
captures 按一下以切換原始碼

傳回最近一次比對的子群組(不包括完整比對)。如果先前沒有比對到任何內容,則傳回 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_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;
}
charpos() 按一下以切換原始碼

傳回掃描指標的字元位置。在「重設」位置,此值為零。在「終止」位置(即字串已用盡),此值為字串的大小。

簡而言之,它是字串中以 0 為基礎的索引。

s = StringScanner.new("abc\u00e4def\u00f6ghi")
s.charpos                # -> 0
s.scan_until(/\u00e4/)   # -> "abc\u00E4"
s.pos                    # -> 5
s.charpos                # -> 4
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)));
}
check(pattern) 按一下以切換原始碼

這會傳回 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(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 1);
}
check_until(pattern) 按一下以切換原始碼

這會傳回 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_check_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 1, 0);
}
clear() 按一下以切換原始碼

等同於 terminate。此方法已過時;請改用 terminate

static VALUE
strscan_clear(VALUE self)
{
    rb_warning("StringScanner#clear is obsolete; use #terminate instead");
    return strscan_terminate(self);
}
concat(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"
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;
}
別名為:<<
empty?() 按一下以切換原始碼

等同於 eos?。此方法已過時;請改用 eos?

static VALUE
strscan_empty_p(VALUE self)
{
    rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
    return strscan_eos_p(self);
}
eos?() 按一下以切換原始碼

如果掃描指標位於字串的結尾,則傳回 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_eos_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return EOS_P(p) ? Qtrue : Qfalse;
}
exist?(pattern) 按一下以切換原始碼

向前查看字串中是否任何地方存在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_exist_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 0);
}
fixed_anchor? → true 或 false 按一下以切換來源

scanner 是否使用固定錨定模式。

如果使用固定錨定模式,\A 永遠會比對字串開頭。否則,\A 永遠會比對目前位置。

static VALUE
strscan_fixed_anchor_p(VALUE self)
{
    struct strscanner *p;
    p = check_strscan(self);
    return p->fixed_anchor_p ? Qtrue : Qfalse;
}
get_byte() 按一下以切換來源

掃描一個位元組並傳回。此方法不區分多位元組字元。另請參閱: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
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]));
}
getbyte() 按一下以切換來源

等同於 get_byte。此方法已過時;請改用 get_byte

static VALUE
strscan_getbyte(VALUE self)
{
    rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
    return strscan_get_byte(self);
}
getch() 按一下以切換來源

掃描一個字元並傳回。此方法區分多位元組字元。

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
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]));
}
inspect() 按一下以切換來源

傳回表示 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_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;
}
match?(pattern) 按一下以切換來源

測試給定的 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_match_p(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 0, 0, 1);
}
matched() 按一下以切換來源

傳回最後比對的字串。

s = StringScanner.new('test string')
s.match?(/\w+/)     # -> 4
s.matched           # -> "test"
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]));
}
matched?() 按一下以切換來源

僅當最後比對成功時傳回 true

s = StringScanner.new('test string')
s.match?(/\w+/)     # => 4
s.matched?          # => true
s.match?(/\d+/)     # => nil
s.matched?          # => false
static VALUE
strscan_matched_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return MATCHED_P(p) ? Qtrue : Qfalse;
}
matched_size() 按一下以切換來源

傳回最近一次比對的位元組大小,或如果沒有最近一次比對,則傳回 nil。這與 matched.size 不同,後者會傳回字元大小。

s = StringScanner.new('test string')
s.check /\w+/           # -> "test"
s.matched_size          # -> 4
s.check /\d+/           # -> nil
s.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]);
}
named_captures → hash 按一下以切換來源

傳回比對正規表示式的字串變數的雜湊。

scan = StringScanner.new('foobarbaz')
scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}
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;
}
peek(len) 按一下以切換原始碼

擷取對應於 string[pos,len] 的字串,不會前進掃描指標。

s = StringScanner.new('test string')
s.peek(7)          # => "test st"
s.peek(7)          # => "test st"
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);
}
peep(p1) 按一下以切換原始碼

等於 peek。此方法已過時;請改用 peek

static VALUE
strscan_peep(VALUE self, VALUE vlen)
{
    rb_warning("StringScanner#peep is obsolete; use #peek instead");
    return strscan_peek(self, vlen);
}
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() 按一下以切換原始碼

傳回掃描指標的位元組位置。在「重設」位置,此值為零。在「終止」位置(亦即字串已用盡),此值為字串的位元組大小。

簡而言之,它是字串位元組的 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_get_pos(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return INT2FIX(p->curr);
}
別名:pointer
pos=(n) 按一下以切換原始碼

設定掃描指標的位元組位置。

s = StringScanner.new('test string')
s.pos = 7            # -> 7
s.rest               # -> "ring"
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);
}
別名:pointer=
post_match() 按一下以切換原始碼

傳回最後一次掃描的配對(以正規表示式觀點)。

s = StringScanner.new('test string')
s.scan(/\w+/)           # -> "test"
s.scan(/\s+/)           # -> " "
s.pre_match             # -> "test"
s.post_match            # -> "string"
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));
}
pre_match() 按一下以切換原始碼

傳回最後一次掃描的配對(以正規表示式觀點)。

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]));
}
reset() 按一下以切換原始碼

重設掃描指標(索引 0)並清除配對資料。

static VALUE
strscan_reset(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    p->curr = 0;
    CLEAR_MATCH_STATUS(p);
    return self;
}
rest() 按一下以切換原始碼

傳回字串的「剩餘部分」(亦即掃描指標之後的所有內容)。如果沒有更多資料(eos? = 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));
}
rest?() 按一下以切換原始碼

如果且僅如果字串中有更多資料,則傳回 true。請參閱 eos?。此方法已過時;請改用 eos?

s = StringScanner.new('test string')
# These two are opposites
s.eos? # => false
s.rest? # => true
static VALUE
strscan_rest_p(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return EOS_P(p) ? Qfalse : Qtrue;
}
rest_size() 按一下以切換原始碼

s.rest_size 等於 s.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);
}
restsize() 按一下以切換原始碼

s.restsize 等同於 s.rest_size。此方法已過時;請改用 rest_size

static VALUE
strscan_restsize(VALUE self)
{
    rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
    return strscan_rest_size(self);
}
scan(pattern) → String 按一下以切換來源

嘗試在目前位置比對 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(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 1);
}
scan_full(pattern, advance_pointer_p, return_string_p) 按一下以切換來源

測試目前掃描指標是否比對到指定的 pattern。如果 advance_pointer_p 為 true,則推進掃描指標。如果 return_string_p 為 true,則傳回比對到的字串。比對暫存器會受到影響。

「full」表示「帶有完整參數的 #scan」。

static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
}
scan_until(pattern) 按一下以切換來源

掃描字串,直到比對到 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_scan_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 1, 0);
}
search_full(pattern, advance_pointer_p, return_string_p) 按一下以切換來源

掃描字串,直到比對到 pattern。如果 advance_pointer_p 為 true,則推進掃描指標;否則不推進。如果 return_string_p 為 true,則傳回比對到的字串;否則傳回推進的位元組數。此方法會影響比對暫存器。

static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
    return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
}
size 按一下以切換來源

傳回最近一次比對中的子群組數量。完整比對計為一個子群組。

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.scan(/(\w+) (\w+) (\d+) /)       # -> "Fri Dec 12 "
s.size                             # -> 4
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);
}
skip(pattern) 按一下以切換來源

嘗試從掃描指標開始跳過指定的 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(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 1);
}
skip_until(pattern) 按一下以切換來源

推進掃描指標,直到比對到並消耗 pattern。傳回推進的位元組數,或如果沒有找到比對,則傳回 nil

向前尋找以比對 pattern,並將掃描指標推進到比對的結束位置。傳回推進的字元數,或如果比對失敗,則傳回 nil

類似於 scan_until,但不會傳回中間的字串。

s = StringScanner.new("Fri Dec 12 1975 14:39")
s.skip_until /12/           # -> 10
s                           #
static VALUE
strscan_skip_until(VALUE self, VALUE re)
{
    return strscan_do_scan(self, re, 1, 0, 0);
}
string() 按一下以切換來源

傳回正在掃描的字串。

static VALUE
strscan_get_string(VALUE self)
{
    struct strscanner *p;

    GET_SCANNER(self, p);
    return p->str;
}
string=(str) 按一下以切換來源

將正在掃描的字串變更為 str 並重設掃描器。傳回 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;
}
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() 按一下以切換來源

將掃描指標設定為前一個位置。只會記住一個前一個位置,而且會隨著每個掃描作業而變更。

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_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;
}
values_at( i1, i2, ... iN ) → an_array 按一下以切換來源

傳回在最近的配對中,指定索引處的子群組。如果先前沒有配對,則傳回 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_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;
}

私有實例方法

dup 按一下以切換來源
clone

複製一個 StringScanner 物件。

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