MatchData 類別
MatchData
封裝將 Regexp
與字串配對的結果。它是由 Regexp#match
和 String#match
傳回,也會儲存在由 Regexp.last_match
傳回的**全域變數**中。
用法
url = 'https://ruby-docs.dev.org.tw/en/2.5.0/MatchData.html' m = url.match(/(\d\.?)+/) # => #<MatchData "2.5.0" 1:"0"> m.string # => "https://ruby-docs.dev.org.tw/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
是另一個目標字串、正規表示式、配對和擷取與 self
相同的 MatchData 物件,則傳回 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); }
傳回指定名稱的指定擷取的 hash。
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"}
如果未定義任何指定名稱的擷取,則傳回空的 hash
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
當給定字串或符號引數 名稱
時,傳回命名比對的比對子字串的長度
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"}
如果關鍵字引數 符號化名稱
給定 true 值,則結果雜湊中的金鑰為符號
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]
當給定字串或符號引數 名稱
時,傳回命名比對的開始和結束偏移
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
(即 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
中的第一個比對(也就是 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
中的比對和擷取,這些索引可能包含下列任何組合:
-
整數。
-
範圍。
-
名稱(字串和符號)。
範例
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; }