类 MatchData
MatchData
封装了将 Regexp
与字符串匹配的结果。它由 Regexp#match
和 String#match
返回,并存储在由 Regexp.last_match
返回的全局变量中。
用法
url = 'https://docs.ruby-lang.org.cn/en/2.5.0/MatchData.html' m = url.match(/(\d\.?)+/) # => #<MatchData "2.5.0" 1:"0"> m.string # => "https://docs.ruby-lang.org.cn/en/2.5.0/MatchData.html" m.regexp # => /(\d\.?)+/ # entire matched substring: m[0] # => "2.5.0" # Working with unnamed captures m = url.match(%r{([^/]+)/([^/]+)\.html$}) m.captures # => ["2.5.0", "MatchData"] m[1] # => "2.5.0" m.values_at(1, 2) # => ["2.5.0", "MatchData"] # Working with named captures m = url.match(%r{(?<version>[^/]+)/(?<module>[^/]+)\.html$}) m.captures # => ["2.5.0", "MatchData"] m.named_captures # => {"version"=>"2.5.0", "module"=>"MatchData"} m[:version] # => "2.5.0" m.values_at(:version, :module) # => ["2.5.0", "MatchData"] # Numerical indexes are working, too m[1] # => "2.5.0" m.values_at(1, 2) # => ["2.5.0", "MatchData"]
全局变量等效性¶ ↑
最后一个 MatchData
的部分(由 Regexp.last_match
返回)也作为全局变量别名。
-
$~
是Regexp.last_match
; -
$&
是Regexp.last_match
[ 0 ]
; -
$1
、$2
等是Regexp.last_match
[ i ]
(按数字捕获); -
$`
是Regexp.last_match
.pre_match
; -
$'
是Regexp.last_match
.post_match
; -
$+
是Regexp.last_match
[ -1 ]
(最后一个捕获)。
另请参阅 Regexp
文档中的“特殊全局变量”部分。
公共实例方法
如果 object
是另一个 MatchData 对象,其目标字符串、正则表达式、匹配和捕获与 self
相同,则返回 true
,否则返回 false
。
当给出参数 index
、+start 和 length
或 range
时,以 Array#[]
的风格返回匹配和捕获。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<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"]
当给出字符串或符号参数 name
时,返回给定名称的匹配子字符串。
m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" bar:"ge"> m['foo'] # => "h" m[:bar] # => "ge"
如果多个捕获具有相同的名称,则返回最后一个匹配的子字符串。
m = /(?<foo>.)(?<foo>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" foo:"oge"> m[:foo] #=> "oge" m = /\W(?<foo>.+)|\w(?<foo>.+)|(?<foo>.+)/.match("hoge") #<MatchData "hoge" foo:nil foo:"oge" foo:nil> m[:foo] #=> "oge"
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; } if (beg+len > num_regs) { len = num_regs - beg; } return match_ary_subseq(match, beg, len, Qnil); } }
返回指定匹配开始处的偏移量(以字符为单位)。
当给出非负整数参数 n
时,返回第 n
个匹配开始处的偏移量。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" m.begin(0) # => 1 m[3] # => "113" m.begin(3) # => 3 m = /(т)(е)(с)/.match('тест') # => #<MatchData "тес" 1:"т" 2:"е" 3:"с"> m[0] # => "тес" m.begin(0) # => 0 m[3] # => "с" m.begin(3) # => 2
当给出字符串或符号参数 name
时,返回命名匹配开始处的偏移量。
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge") # => #<MatchData "hog" foo:"h" bar:"g"> m[:foo] # => "h" m.begin('foo') # => 0 m[:bar] # => "g" m.begin(:bar) # => 2
相关:MatchData#end
、MatchData#offset
、MatchData#byteoffset
。
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); backref_number_check(regs, i); if (BEG(i) < 0) return Qnil; update_char_offset(match); return LONG2NUM(RMATCH_EXT(match)->char_offset[i].beg); }
返回一个包含第 n 个匹配的基于字节的开始和结束偏移量的两个元素数组。n 可以是字符串或符号来引用命名捕获。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") m.byteoffset(0) #=> [1, 7] m.byteoffset(4) #=> [6, 7] m = /(?<foo>.)(.)(?<bar>.)/.match("hoge") p m.byteoffset(:foo) #=> [0, 1] p m.byteoffset(:bar) #=> [2, 3]
static VALUE match_byteoffset(VALUE match, VALUE n) { int i = match_backref_number(match, n); struct re_registers *regs = RMATCH_REGS(match); match_check(match); backref_number_check(regs, i); if (BEG(i) < 0) return rb_assoc_new(Qnil, Qnil); return rb_assoc_new(LONG2NUM(BEG(i)), LONG2NUM(END(i))); }
返回捕获的数组,它们是除 m[0]
之外的所有匹配项。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" m.captures # => ["H", "X", "113", "8"]
相关:MatchData.to_a
。
static VALUE match_captures(VALUE match) { return match_array(match, 1); }
返回给定名称的命名捕获的哈希。
m = /(?<hours>\d{2}):(?<minutes>\d{2}):(?<seconds>\d{2})/.match("18:37:22") m.deconstruct_keys([:hours, :minutes]) # => {:hours => "18", :minutes => "37"} m.deconstruct_keys(nil) # => {:hours => "18", :minutes => "37", :seconds => "22"}
如果未定义命名捕获,则返回空哈希。
m = /(\d{2}):(\d{2}):(\d{2})/.match("18:37:22") m.deconstruct_keys(nil) # => {}
static VALUE match_deconstruct_keys(VALUE match, VALUE keys) { VALUE h; long i; match_check(match); if (NIL_P(RMATCH(match)->regexp)) { return rb_hash_new_with_size(0); } if (NIL_P(keys)) { h = rb_hash_new_with_size(onig_number_of_names(RREGEXP_PTR(RMATCH(match)->regexp))); struct MEMO *memo; memo = MEMO_NEW(h, match, 1); onig_foreach_name(RREGEXP_PTR(RMATCH(match)->regexp), match_named_captures_iter, (void*)memo); return h; } Check_Type(keys, T_ARRAY); if (onig_number_of_names(RREGEXP_PTR(RMATCH(match)->regexp)) < RARRAY_LEN(keys)) { return rb_hash_new_with_size(0); } h = rb_hash_new_with_size(RARRAY_LEN(keys)); for (i=0; i<RARRAY_LEN(keys); i++) { VALUE key = RARRAY_AREF(keys, i); VALUE name; Check_Type(key, T_SYMBOL); name = rb_sym2str(key); int num = NAME_TO_NUMBER(RMATCH_REGS(match), RMATCH(match)->regexp, RMATCH(match)->regexp, RSTRING_PTR(name), RSTRING_END(name)); if (num >= 0) { rb_hash_aset(h, key, rb_reg_nth_match(num, match)); } else { return h; } } return h; }
返回指定匹配结束处的偏移量(以字符为单位)。
当给出非负整数参数 n
时,返回第 n
个匹配结束处的偏移量。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" m.end(0) # => 7 m[3] # => "113" m.end(3) # => 6 m = /(т)(е)(с)/.match('тест') # => #<MatchData "тес" 1:"т" 2:"е" 3:"с"> m[0] # => "тес" m.end(0) # => 3 m[3] # => "с" m.end(3) # => 3
当给出字符串或符号参数 name
时,返回命名匹配结束处的偏移量。
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge") # => #<MatchData "hog" foo:"h" bar:"g"> m[:foo] # => "h" m.end('foo') # => 1 m[:bar] # => "g" m.end(:bar) # => 3
相关:MatchData#begin
、MatchData#offset
、MatchData#byteoffset
。
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); backref_number_check(regs, i); if (BEG(i) < 0) return Qnil; update_char_offset(match); return LONG2NUM(RMATCH_EXT(match)->char_offset[i].end); }
返回 self
的整数哈希值,基于目标字符串、正则表达式、匹配和捕获。
另请参见 Object#hash
。
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); }
返回 self
的字符串表示形式。
m = /.$/.match("foo") # => #<MatchData "o"> m.inspect # => "#<MatchData \"o\">" m = /(.)(.)(.)/.match("foo") # => #<MatchData "foo" 1:"f" 2:"o" 3:"o"> m.inspect # => "#<MatchData \"foo\" 1:\"f\" 2:\"o\ m = /(.)(.)?(.)/.match("fo") # => #<MatchData "fo" 1:"f" 2:nil 3:"o"> m.inspect # => "#<MatchData \"fo\" 1:\"f\" 2:nil 3:\"o\">"
相关:MatchData#to_s
。
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 (NIL_P(v)) rb_str_buf_cat2(str, "nil"); else rb_str_buf_append(str, rb_str_inspect(v)); } rb_str_buf_cat2(str, ">"); return str; }
返回与给定参数相对应的匹配子字符串。
当给出非负参数 n
时,返回第 n
次匹配的匹配子字符串。
m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8" 5:nil> m.match(0) # => "HX1138" m.match(4) # => "8" m.match(5) # => nil
当给出字符串或符号参数 name
时,返回给定名称的匹配子字符串。
m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" bar:"ge"> m.match('foo') # => "h" m.match(:bar) # => "ge"
static VALUE match_nth(VALUE match, VALUE n) { int i = match_backref_number(match, n); struct re_registers *regs = RMATCH_REGS(match); backref_number_check(regs, i); long start = BEG(i), end = END(i); if (start < 0) return Qnil; return rb_str_subseq(RMATCH(match)->str, start, end - start); }
返回与给定参数相对应的匹配子字符串的长度(以字符为单位)。
当给出非负参数 n
时,返回第 n
次匹配的匹配子字符串的长度。
m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8" 5:nil> m.match_length(0) # => 6 m.match_length(4) # => 1 m.match_length(5) # => nil
当给出字符串或符号参数 name
时,返回命名匹配的匹配子字符串的长度。
m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" bar:"ge"> m.match_length('foo') # => 1 m.match_length(:bar) # => 2
static VALUE match_nth_length(VALUE match, VALUE n) { int i = match_backref_number(match, n); struct re_registers *regs = RMATCH_REGS(match); match_check(match); backref_number_check(regs, i); if (BEG(i) < 0) return Qnil; update_char_offset(match); const struct rmatch_offset *const ofs = &RMATCH_EXT(match)->char_offset[i]; return LONG2NUM(ofs->end - ofs->beg); }
返回命名捕获的哈希表;每个键都是捕获名称;每个值都是其捕获的字符串或 nil
。
m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" bar:"ge"> m.named_captures # => {"foo"=>"h", "bar"=>"ge"} m = /(?<a>.)(?<b>.)/.match("01") # => #<MatchData "01" a:"0" b:"1"> m.named_captures #=> {"a" => "0", "b" => "1"} m = /(?<a>.)(?<b>.)?/.match("0") # => #<MatchData "0" a:"0" b:nil> m.named_captures #=> {"a" => "0", "b" => nil} m = /(?<a>.)(?<a>.)/.match("01") # => #<MatchData "01" a:"0" a:"1"> m.named_captures #=> {"a" => "1"}
如果关键字参数 symbolize_names
给出了一个真值,则结果哈希表中的键是符号。
m = /(?<a>.)(?<a>.)/.match("01") # => #<MatchData "01" a:"0" a:"1"> m.named_captures(symbolize_names: true) #=> {:a => "1"}
static VALUE match_named_captures(int argc, VALUE *argv, VALUE match) { VALUE hash; struct MEMO *memo; match_check(match); if (NIL_P(RMATCH(match)->regexp)) return rb_hash_new(); VALUE opt; VALUE symbolize_names = 0; rb_scan_args(argc, argv, "0:", &opt); if (!NIL_P(opt)) { static ID keyword_ids[1]; VALUE symbolize_names_val; if (!keyword_ids[0]) { keyword_ids[0] = rb_intern_const("symbolize_names"); } rb_get_kwargs(opt, keyword_ids, 0, 1, &symbolize_names_val); if (!UNDEF_P(symbolize_names_val) && RTEST(symbolize_names_val)) { symbolize_names = 1; } } hash = rb_hash_new(); memo = MEMO_NEW(hash, match, symbolize_names); onig_foreach_name(RREGEXP(RMATCH(match)->regexp)->ptr, match_named_captures_iter, (void*)memo); return hash; }
返回捕获名称的数组(参见 命名捕获)。
m = /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge") # => #<MatchData "hog" foo:"h" bar:"o" baz:"g"> m.names # => ["foo", "bar", "baz"] m = /foo/.match('foo') # => #<MatchData "foo"> m.names # => [] # No named captures.
等同于
m = /(?<foo>.)(?<bar>.)(?<baz>.)/.match("hoge") m.regexp.names # => ["foo", "bar", "baz"]
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); }
返回一个包含指定匹配的开始和结束偏移量(以字符为单位)的 2 元素数组。
当给出非负整数参数 n
时,返回第 n
次匹配的开始和结束偏移量。
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" m.offset(0) # => [1, 7] m[3] # => "113" m.offset(3) # => [3, 6] m = /(т)(е)(с)/.match('тест') # => #<MatchData "тес" 1:"т" 2:"е" 3:"с"> m[0] # => "тес" m.offset(0) # => [0, 3] m[3] # => "с" m.offset(3) # => [2, 3]
当给出字符串或符号参数 name
时,返回命名匹配的开始和结束偏移量。
m = /(?<foo>.)(.)(?<bar>.)/.match("hoge") # => #<MatchData "hog" foo:"h" bar:"g"> m[:foo] # => "h" m.offset('foo') # => [0, 1] m[:bar] # => "g" m.offset(:bar) # => [2, 3]
相关:MatchData#byteoffset
,MatchData#begin
,MatchData#end
。
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); backref_number_check(regs, i); if (BEG(i) < 0) return rb_assoc_new(Qnil, Qnil); update_char_offset(match); return rb_assoc_new(LONG2NUM(RMATCH_EXT(match)->char_offset[i].beg), LONG2NUM(RMATCH_EXT(match)->char_offset[i].end)); }
返回目标字符串中从第一个匹配项(即 `self[0]`)的末尾到字符串末尾的子字符串;等效于正则表达式全局变量 `$'`
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" 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); return str; }
返回目标字符串中从其开头到第一个匹配项(即 `self[0]`)的子字符串;等效于正则表达式全局变量 `$`
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m[0] # => "HX1138" 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)); return str; }
返回生成匹配的正则表达式
m = /a.*b/.match("abc") # => #<MatchData "ab"> 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)); RB_OBJ_WRITE(match, &RMATCH(match)->regexp, regexp); } return regexp; }
返回匹配数组的大小
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m.size # => 5
static VALUE match_size(VALUE match) { match_check(match); return INT2FIX(RMATCH_REGS(match)->num_regs); }
如果目标字符串被冻结,则返回目标字符串;否则,返回目标字符串的冻结副本
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m.string # => "THX1138."
static VALUE match_string(VALUE match) { match_check(match); return RMATCH(match)->str; /* str is frozen */ }
返回匹配项的数组
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m.to_a # => ["HX1138", "H", "X", "113", "8"]
static VALUE match_to_a(VALUE match) { return match_array(match, 0); }
返回匹配的字符串
m = /(.)(.)(\d+)(\d)/.match("THX1138.") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m.to_s # => "HX1138" m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") # => #<MatchData "hoge" foo:"h" bar:"ge"> m.to_s # => "hoge"
static VALUE match_to_s(VALUE match) { VALUE str = rb_reg_last_match(match_check(match)); if (NIL_P(str)) str = rb_str_new(0,0); return str; }
返回给定 `indexes` 处的匹配项和捕获项,这些 `indexes` 可能包含任何混合的
-
整数。
-
范围。
-
名称(字符串和符号)。
示例
m = /(.)(.)(\d+)(\d)/.match("THX1138: The Movie") # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8"> m.values_at(0, 2, -2) # => ["HX1138", "X", "113"] m.values_at(1..2, -1) # => ["H", "X", "8"] m = /(?<a>\d+) *(?<op>[+\-*\/]) *(?<b>\d+)/.match("1 + 2") # => #<MatchData "1 + 2" a:"1" op:"+" b:"2"> m.values_at(0, 1..2, :a, :b, :op) # => ["1 + 2", "1", "+", "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; }