класс MatchData
MatchData — это тип специальной переменной $~, и это тип объекта, возвращаемого Regexp#match и Regexp.last_match. Он обобщает все результаты совпадения шаблона, результаты, обычно доступные через специальные переменные $&, $', $`, $1, $2, и так далее.
Методы экземпляра Public
static VALUE
match_equal(VALUE match1, VALUE match2)
{
const struct re_registers *regs1, *regs2;
if (match1 == match2) return Qtrue;
if (!RB_TYPE_P(match2, T_MATCH)) return Qfalse;
if (!rb_str_equal(RMATCH(match1)->str, RMATCH(match2)->str)) return Qfalse;
if (!rb_reg_equal(match_regexp(match1), match_regexp(match2))) return Qfalse;
regs1 = RMATCH_REGS(match1);
regs2 = RMATCH_REGS(match2);
if (regs1->num_regs != regs2->num_regs) return Qfalse;
if (memcmp(regs1->beg, regs2->beg, regs1->num_regs * sizeof(*regs1->beg))) return Qfalse;
if (memcmp(regs1->end, regs2->end, regs1->num_regs * sizeof(*regs1->end))) return Qfalse;
return Qtrue;
} Равенство — Два объекта matchdata равны, если их целевые строки, шаблоны и сопоставленные позиции идентичны.
static VALUE
match_aref(int argc, VALUE *argv, VALUE match)
{
VALUE idx, rest, re;
match_check(match);
rb_scan_args(argc, argv, "11", &idx, &rest);
if (NIL_P(rest)) {
if (FIXNUM_P(idx)) {
if (FIX2INT(idx) >= 0) {
return rb_reg_nth_match(FIX2INT(idx), match);
}
}
else {
const char *p;
int num;
switch (TYPE(idx)) {
case T_SYMBOL:
idx = rb_sym2str(idx);
/* fall through */
case T_STRING:
p = StringValuePtr(idx);
re = RMATCH(match)->regexp;
if (NIL_P(re) || !rb_enc_compatible(RREGEXP(re)->src, idx) ||
(num = name_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp,
p, p + RSTRING_LEN(idx))) < 1) {
name_to_backref_error(idx);
}
return rb_reg_nth_match(num, match);
default:
break;
}
}
}
return rb_ary_aref(argc, argv, match_to_a(match));
} Ссылка на совпадение — MatchData действует как массив и может быть обращен с помощью обычных методов индексирования массивов. mtch[0] эквивалентно специальной переменной $&, и возвращает всю сопоставленную строку. mtch[1], mtch[2], и так далее возвращают значения сопоставленных обратных ссылок (частей шаблона между круглыми скобками).
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m #=> #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
m[0] #=> "HX1138"
m[1, 2] #=> ["H", "X"]
m[1..3] #=> ["H", "X", "113"]
m[-3, 2] #=> ["X", "113"]
m = /(?<foo>a+)b/.match("ccaaab")
m #=> #<MatchData "aaab" foo:"aaa">
m["foo"] #=> "aaa"
m[:foo] #=> "aaa"
static VALUE
match_begin(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
if (i < 0 || regs->num_regs <= i)
rb_raise(rb_eIndexError, "index %d out of matches", i);
if (BEG(i) < 0)
return Qnil;
update_char_offset(match);
return INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg);
} Возвращает смещение начала n-го элемента массива совпадений в строке. n может быть строкой или символом для ссылки на именованный захват.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.begin(0) #=> 1
m.begin(2) #=> 2
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.begin(:foo) #=> 0
p m.begin(:bar) #=> 2
static VALUE
match_captures(VALUE match)
{
return match_array(match, 1);
} Возвращает массив захватов; эквивалентно mtch.to_a[1..-1].
f1,f2,f3,f4 = /(.)(.)(\d+)(\d)/.match("THX1138.").captures
f1 #=> "H"
f2 #=> "X"
f3 #=> "113"
f4 #=> "8"
static VALUE
match_end(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
if (i < 0 || regs->num_regs <= i)
rb_raise(rb_eIndexError, "index %d out of matches", i);
if (BEG(i) < 0)
return Qnil;
update_char_offset(match);
return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end);
} Возвращает смещение символа, непосредственно следующего за концом n-го элемента массива совпадений в строке. n может быть строкой или символом для ссылки на именованный захват.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.end(0) #=> 7
m.end(2) #=> 3
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.end(:foo) #=> 1
p m.end(:bar) #=> 3
static VALUE
match_equal(VALUE match1, VALUE match2)
{
const struct re_registers *regs1, *regs2;
if (match1 == match2) return Qtrue;
if (!RB_TYPE_P(match2, T_MATCH)) return Qfalse;
if (!rb_str_equal(RMATCH(match1)->str, RMATCH(match2)->str)) return Qfalse;
if (!rb_reg_equal(match_regexp(match1), match_regexp(match2))) return Qfalse;
regs1 = RMATCH_REGS(match1);
regs2 = RMATCH_REGS(match2);
if (regs1->num_regs != regs2->num_regs) return Qfalse;
if (memcmp(regs1->beg, regs2->beg, regs1->num_regs * sizeof(*regs1->beg))) return Qfalse;
if (memcmp(regs1->end, regs2->end, regs1->num_regs * sizeof(*regs1->end))) return Qfalse;
return Qtrue;
} Равенство — Два объекта matchdata равны, если их целевые строки, шаблоны и сопоставленные позиции идентичны.
static VALUE
match_hash(VALUE match)
{
const struct re_registers *regs;
st_index_t hashval = rb_hash_start(rb_str_hash(RMATCH(match)->str));
rb_hash_uint(hashval, reg_hash(match_regexp(match)));
regs = RMATCH_REGS(match);
hashval = rb_hash_uint(hashval, regs->num_regs);
hashval = rb_hash_uint(hashval, rb_memhash(regs->beg, regs->num_regs * sizeof(*regs->beg)));
hashval = rb_hash_uint(hashval, rb_memhash(regs->end, regs->num_regs * sizeof(*regs->end)));
hashval = rb_hash_end(hashval);
return LONG2FIX(hashval);
} Генерирует хеш на основе целевой строки, регулярного выражения и сопоставленных позиций этого объекта matchdata.
См. также Object#hash.
static VALUE
match_inspect(VALUE match)
{
VALUE cname = rb_class_path(rb_obj_class(match));
VALUE str;
int i;
struct re_registers *regs = RMATCH_REGS(match);
int num_regs = regs->num_regs;
struct backref_name_tag *names;
VALUE regexp = RMATCH(match)->regexp;
if (regexp == 0) {
return rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)match);
}
else if (NIL_P(regexp)) {
return rb_sprintf("#<%"PRIsVALUE": %"PRIsVALUE">",
cname, rb_reg_nth_match(0, match));
}
names = ALLOCA_N(struct backref_name_tag, num_regs);
MEMZERO(names, struct backref_name_tag, num_regs);
onig_foreach_name(RREGEXP(regexp)->ptr,
match_inspect_name_iter, names);
str = rb_str_buf_new2("#<");
rb_str_append(str, cname);
for (i = 0; i < num_regs; i++) {
VALUE v;
rb_str_buf_cat2(str, " ");
if (0 < i) {
if (names[i].name)
rb_str_buf_cat(str, (const char *)names[i].name, names[i].len);
else {
rb_str_catf(str, "%d", i);
}
rb_str_buf_cat2(str, ":");
}
v = rb_reg_nth_match(i, match);
if (v == Qnil)
rb_str_buf_cat2(str, "nil");
else
rb_str_buf_append(str, rb_str_inspect(v));
}
rb_str_buf_cat2(str, ">");
return str;
} Возвращает удобочитаемый вид объекта mtch.
puts /.$/.match("foo").inspect
#=> #<MatchData "o">
puts /(.)(.)(.)/.match("foo").inspect
#=> #<MatchData "foo" 1:"f" 2:"o" 3:"o">
puts /(.)(.)?(.)/.match("fo").inspect
#=> #<MatchData "fo" 1:"f" 2:nil 3:"o">
puts /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").inspect
#=> #<MatchData "hog" foo:"h" bar:"o" baz:"g">
static VALUE
match_size(VALUE match)
{
match_check(match);
return INT2FIX(RMATCH_REGS(match)->num_regs);
} Возвращает количество элементов в массиве совпадений.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length #=> 5
m.size #=> 5
static VALUE
match_names(VALUE match)
{
match_check(match);
if (NIL_P(RMATCH(match)->regexp))
return rb_ary_new_capa(0);
return rb_reg_names(RMATCH(match)->regexp);
} Возвращает список имен захватов в виде массива строк. Это то же самое, что mtch.regexp.names.
/(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge").names
#=> ["foo", "bar", "baz"]
m = /(?<x>.)(?<y>.)?/.match("a") #=> #<MatchData "a" x:"a" y:nil>
m.names #=> ["x", "y"]
static VALUE
match_offset(VALUE match, VALUE n)
{
int i = match_backref_number(match, n);
struct re_registers *regs = RMATCH_REGS(match);
match_check(match);
if (i < 0 || regs->num_regs <= i)
rb_raise(rb_eIndexError, "index %d out of matches", i);
if (BEG(i) < 0)
return rb_assoc_new(Qnil, Qnil);
update_char_offset(match);
return rb_assoc_new(INT2FIX(RMATCH(match)->rmatch->char_offset[i].beg),
INT2FIX(RMATCH(match)->rmatch->char_offset[i].end));
} Возвращает массив из двух элементов, содержащий начальное и конечное смещения n-го совпадения. n может быть строкой или символом для ссылки на именованный захват.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.offset(0) #=> [1, 7]
m.offset(4) #=> [6, 7]
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
p m.offset(:foo) #=> [0, 1]
p m.offset(:bar) #=> [2, 3]
VALUE
rb_reg_match_post(VALUE match)
{
VALUE str;
long pos;
struct re_registers *regs;
if (NIL_P(match)) return Qnil;
match_check(match);
regs = RMATCH_REGS(match);
if (BEG(0) == -1) return Qnil;
str = RMATCH(match)->str;
pos = END(0);
str = rb_str_subseq(str, pos, RSTRING_LEN(str) - pos);
if (OBJ_TAINTED(match)) OBJ_TAINT(str);
return str;
} Возвращает часть исходной строки после текущего совпадения. Эквивалентно специальной переменной $'.
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.post_match #=> ": The Movie"
VALUE
rb_reg_match_pre(VALUE match)
{
VALUE str;
struct re_registers *regs;
if (NIL_P(match)) return Qnil;
match_check(match);
regs = RMATCH_REGS(match);
if (BEG(0) == -1) return Qnil;
str = rb_str_subseq(RMATCH(match)->str, 0, BEG(0));
if (OBJ_TAINTED(match)) OBJ_TAINT(str);
return str;
} Возвращает часть исходной строки перед текущим совпадением. Эквивалентно специальной переменной $`.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.pre_match #=> "T"
static VALUE
match_regexp(VALUE match)
{
VALUE regexp;
match_check(match);
regexp = RMATCH(match)->regexp;
if (NIL_P(regexp)) {
VALUE str = rb_reg_nth_match(0, match);
regexp = rb_reg_regcomp(rb_reg_quote(str));
RMATCH(match)->regexp = regexp;
}
return regexp;
} Возвращает регулярное выражение.
m = /a.*b/.match("abc")
m.regexp #=> /a.*b/
static VALUE
match_size(VALUE match)
{
match_check(match);
return INT2FIX(RMATCH_REGS(match)->num_regs);
} Возвращает количество элементов в массиве совпадений.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length #=> 5
m.size #=> 5
static VALUE
match_string(VALUE match)
{
match_check(match);
return RMATCH(match)->str; /* str is frozen */
} Возвращает замороженную копию строки, переданной в match.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.string #=> "THX1138."
static VALUE
match_to_a(VALUE match)
{
return match_array(match, 0);
} Возвращает массив совпадений.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.to_a #=> ["HX1138", "H", "X", "113", "8"]
Поскольку to_a вызывается при расширении *переменной, существует полезное сокращение для извлечения сопоставленных полей. Это немного медленнее, чем прямой доступ к полям (поскольку генерируется промежуточный массив).
all,f1,f2,f3 = * /(.)(.)(\d+)(\d)/.match("THX1138.")
all #=> "HX1138"
f1 #=> "H"
f2 #=> "X"
f3 #=> "113"
static VALUE
match_to_s(VALUE match)
{
VALUE str = rb_reg_last_match(match);
match_check(match);
if (NIL_P(str)) str = rb_str_new(0,0);
if (OBJ_TAINTED(match)) OBJ_TAINT(str);
if (OBJ_TAINTED(RMATCH(match)->str)) OBJ_TAINT(str);
return str;
} Возвращает всю сопоставленную строку.
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.to_s #=> "HX1138"
static VALUE
match_values_at(int argc, VALUE *argv, VALUE match)
{
struct re_registers *regs;
match_check(match);
regs = RMATCH_REGS(match);
return rb_get_values_at(match, regs->num_regs, argc, argv, match_entry);
} Использует каждый индекс для доступа к соответствующим значениям, возвращая массив соответствующих совпадений.
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.to_a #=> ["HX1138", "H", "X", "113", "8"]
m.values_at(0, 2, -2) #=> ["HX1138", "X", "113"]
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.