diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2021-09-16 19:50:29 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2021-09-16 19:55:06 +0900 |
commit | f2cb6288bc6f1d5e693841734ce5eb04ff41c2a9 (patch) | |
tree | 800cdd8a9ae0217362abc0a88b8c8030ced57f02 | |
parent | 09d724e6f846b4e53e8571d41ca7d3055d732d9f (diff) |
[Feature #18172] Add MatchData#match_length
The method to return the length of the matched substring
corresponding to the given argument.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4851
-rw-r--r-- | re.c | 37 | ||||
-rw-r--r-- | test/ruby/test_regexp.rb | 17 |
2 files changed, 54 insertions, 0 deletions
@@ -1335,6 +1335,42 @@ match_nth(VALUE match, VALUE n) return rb_str_subseq(RMATCH(match)->str, start, end - start); } +/* + * call-seq: + * mtch.match_length(n) -> array + * + * Returns the length of the captured substring corresponding to the argument. + * <em>n</em> can be a string or symbol to reference a named capture. + * + * m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + * m.match_length(0) #=> 6 + * m.match_length(4) #=> 1 + * m.match_length(5) #=> nil + * + * m = /(?<foo>.)(.)(?<bar>.+)/.match("hoge") + * 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(match)->rmatch->char_offset[i]; + return LONG2NUM(ofs->end - ofs->beg); +} + #define MATCH_BUSY FL_USER2 void @@ -4136,6 +4172,7 @@ Init_Regexp(void) 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, "match_length", match_nth_length, 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 66a60b8d06..b9e64a47e7 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -490,6 +490,23 @@ class TestRegexp < Test::Unit::TestCase assert_equal("oge\u3042", m.match(:bar)) end + def test_match_matchsubstring + m = /(.)(.)(\d+)(\d)(\w)?/.match("THX1138.") + assert_equal(6, m.match_length(0)) + assert_equal(1, m.match_length(4)) + assert_nil(m.match_length(5)) + + m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044") + assert_equal(1, m.match_length(1)) + assert_nil(m.match_length(2)) + assert_equal(1, m.match_length(3)) + + m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042") + assert_equal(1, m.match_length(:foo)) + assert_nil(m.match_length(:n)) + assert_equal(4, m.match_length(:bar)) + end + def test_match_inspect m = /(...)(...)(...)(...)?/.match("foobarbaz") assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect) |