diff --git a/re.c b/re.c
index 5c5b53dddc..5d5f6fc65c 100644
--- a/re.c
+++ b/re.c
@@ -1302,6 +1302,39 @@ match_end(VALUE match, VALUE n)
return INT2FIX(RMATCH(match)->rmatch->char_offset[i].end);
}
+/*
+ * call-seq:
+ * mtch.match(n) -> string or nil
+ *
+ * Returns the captured substring corresponding to the argument.
+ * n can be a string or symbol to reference a named capture.
+ *
+ * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ * m.match(0) #=> "HX1138"
+ * m.match(4) #=> "8"
+ * m.match(5) #=> nil
+ *
+ * m = /(?.)(.)(?.+)/.match("hoge")
+ * 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);
+}
+
#define MATCH_BUSY FL_USER2
void
@@ -4102,6 +4135,7 @@ Init_Regexp(void)
rb_define_method(rb_cMatch, "offset", match_offset, 1);
rb_define_method(rb_cMatch, "begin", match_begin, 1);
rb_define_method(rb_cMatch, "end", match_end, 1);
+ rb_define_method(rb_cMatch, "match", match_nth, 1);
rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
rb_define_method(rb_cMatch, "[]", match_aref, -1);
rb_define_method(rb_cMatch, "captures", match_captures, 0);
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index af62d944dc..66a60b8d06 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -473,6 +473,23 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("foobarbaz", m.string)
end
+ def test_match_matchsubstring
+ m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.")
+ assert_equal("HX1138", m.match(0))
+ assert_equal("8", m.match(4))
+ assert_nil(m.match(5))
+
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ assert_equal("\u3043", m.match(1))
+ assert_nil(m.match(2))
+ assert_equal("\u3044", m.match(3))
+
+ m = /(?.)(?[^aeiou])?(?.+)/.match("hoge\u3042")
+ assert_equal("h", m.match(:foo))
+ assert_nil(m.match(:n))
+ assert_equal("oge\u3042", m.match(:bar))
+ end
+
def test_match_inspect
m = /(...)(...)(...)(...)?/.match("foobarbaz")
assert_equal('#', m.inspect)