MatchData
MatchData 类
Parent:Object
MatchData
是特殊变量$~
的类型,并且是由Regexp#match
&返回的对象的类型Regexp.last_match
。它封装模式匹配的所有结果,结果通常是通过特殊的变量访问$&
,$'
,$`
,$1
,$2
,等。
公共实例方法
mtch == mtch2→true 或 false 显示来源
平等 - 如果两个匹配数据的目标字符串,模式和匹配位置相同,则两个匹配数据相等。
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 (!RMATCH(match1)->regexp || !RMATCH(match2)->regexp) 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;
}
mtchi → str or nil Show source
mtchstart, length → array
mtchrange → array
mtchname → str or nil
匹配引用 - 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_aref(int argc, VALUE *argv, VALUE match)
{
VALUE idx, length;
match_check(match
rb_scan_args(argc, argv, "11", &idx, &length
if (NIL_P(length)) {
if (FIXNUM_P(idx)) {
return rb_reg_nth_match(FIX2INT(idx), match
}
else {
int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, idx
if (num >= 0) {
return rb_reg_nth_match(num, match
}
else {
return match_ary_aref(match, idx, Qnil
}
}
}
else {
long beg = NUM2LONG(idx
long len = NUM2LONG(length
long num_regs = RMATCH_REGS(match)->num_regs;
if (len < 0) {
return Qnil;
}
if (beg < 0) {
beg += num_regs;
if (beg < 0) return Qnil;
}
else if (beg > num_regs) {
return Qnil;
}
else if (beg+len > num_regs) {
len = num_regs - beg;
}
return match_ary_subseq(match, beg, len, Qnil
}
}
begin(n) → integer Show source
返回字符串中匹配数组的第 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_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
}
captures → array Show source
返回捕获数组; 相当于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_captures(VALUE match)
{
return match_array(match, 1
}
end(n) → integer Show source
返回紧跟在字符串中匹配数组的第 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_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
}
eql?(mtch2) → true or false Show source
平等 - 如果两个匹配数据的目标字符串,模式和匹配位置相同,则两个匹配数据相等。
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 (!RMATCH(match1)->regexp || !RMATCH(match2)->regexp) 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;
}
hash → integer Show source
根据目标字符串,regexp 和匹配的匹配位置产生一个散列。
另请参阅对象#散列。
static VALUE
match_hash(VALUE match)
{
const struct re_registers *regs;
st_index_t hashval;
match_check(match
hashval = rb_hash_start(rb_str_hash(RMATCH(match)->str)
hashval = 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 ST2FIX(hashval
}
inspect → str Show source
返回可打印版本的 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_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_PTR(regexp),
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;
}
length → integer Show source
返回匹配数组中元素的数量。
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length #=> 5
m.size #=> 5
static VALUE
match_size(VALUE match)
{
match_check(match
return INT2FIX(RMATCH_REGS(match)->num_regs
}
named_captures → hash Show source
使用命名捕获返回哈希。
散列的一个关键是指定捕获的名称。散列值是对应组最后一次成功捕获的字符串。
m = /(?<a>.)(?<b>.)/.match("01")
m.named_captures #=> {"a" => "0", "b" => "1"}
m = /(?<a>.)(?<b>.)?/.match("0")
m.named_captures #=> {"a" => "0", "b" => nil}
m = /(?<a>.)(?<a>.)/.match("01")
m.named_captures #=> {"a" => "1"}
m = /(?<a>x)|(?<a>y)/.match("x")
m.named_captures #=> {"a" => "x"}
static VALUE
match_named_captures(VALUE match)
{
VALUE hash;
struct MEMO *memo;
match_check(match
if (NIL_P(RMATCH(match)->regexp))
return rb_hash_new(
hash = rb_hash_new(
memo = MEMO_NEW(hash, match, 0
onig_foreach_name(RREGEXP(RMATCH(match)->regexp)->ptr, match_named_captures_iter, (void*)memo
return hash;
}
names → name1, name2, ...()
以字符串数组的形式返回捕获的名称列表。它与 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_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
}
offset(n) → array Show source
返回包含第 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]
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)
}
post_match → str Show source
返回当前匹配后原始字符串的部分。等同于特殊变量$'
。
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.post_match #=> ": The Movie"
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;
}
pre_match → str Show source
返回当前匹配之前原始字符串的部分。等同于特殊变量$`
。
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.pre_match #=> "T"
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;
}
regexp → regexp Show source
返回正则表达式。
m = /a.*b/.match("abc")
m.regexp #=> /a.*b/
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;
}
size → integer Show source
返回匹配数组中元素的数量。
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.length #=> 5
m.size #=> 5
static VALUE
match_size(VALUE match)
{
match_check(match
return INT2FIX(RMATCH_REGS(match)->num_regs
}
string → str Show source
返回传入的字符串的冻结副本match
。
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.string #=> "THX1138."
static VALUE
match_string(VALUE match)
{
match_check(match
return RMATCH(match)->str; /* str is frozen */
}
to_a → anArray Show source
返回匹配数组。
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_a(VALUE match)
{
return match_array(match, 0
}
to_s → str Show source
返回整个匹配的字符串。
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.to_s #=> "HX1138"
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;
}
values_at(index*) → array Show source
使用每个索引访问匹配值,返回相应匹配的数组。
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie")
m.to_a #=> ["HX1138", "H", "X", "113", "8"]
m.values_at(0, 2, -2) #=> ["HX1138", "X", "113"]
m = /(?<a>\d+) *(?<op>[+\-*\/]) *(?<b>\d+)/.match("1 + 2")
m.to_a #=> ["1 + 2", "1", "+", "2"]
m.values_at(:a, :b, :op) #=> ["1", "2", "+"]
static VALUE
match_values_at(int argc, VALUE *argv, VALUE match)
{
VALUE result;
int i;
match_check(match
result = rb_ary_new2(argc
for (i=0; i<argc; i++) {
if (FIXNUM_P(argv[i])) {
rb_ary_push(result, rb_reg_nth_match(FIX2INT(argv[i]), match)
}
else {
int num = namev_to_backref_number(RMATCH_REGS(match), RMATCH(match)->regexp, argv[i]
if (num >= 0) {
rb_ary_push(result, rb_reg_nth_match(num, match)
}
else {
match_ary_aref(match, argv[i], result
}
}
}
return result;
}