/* * call-seq: * str.scan(pattern) => array * str.scan(pattern) {|match, ...| block } => str * * Both forms iterate through <i>str</i>, matching the pattern (which may be a * <code>Regexp</code> or a <code>String</code>). For each match, a result is * generated and either added to the result array or passed to the block. If * the pattern contains no groups, each individual result consists of the * matched string, <code>$&</code>. If the pattern contains groups, each * individual result is itself an array containing one entry per group. * * a = "cruel world" * a.scan(/\w+/) #=> ["cruel", "world"] * a.scan(/.../) #=> ["cru", "el ", "wor"] * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]] * * And the block form: * * a.scan(/\w+/) {|w| print "<<#{w}>> " } * print "\n" * a.scan(/(.)(.)/) {|x,y| print y, x } * print "\n" * * <em>produces:</em> * * <<cruel>> <<world>> * rceu lowlr */ static VALUE rb_str_scan(str, pat) VALUE str, pat; { VALUE result; long start = 0; VALUE match = Qnil; char *p = RSTRING(str)->ptr; long len = RSTRING(str)->len; pat = get_pat(pat, 1); if (!rb_block_given_p()) { VALUE ary = rb_ary_new(); while (!NIL_P(result = scan_once(str, pat, &start))) { match = rb_backref_get(); rb_ary_push(ary, result); } rb_backref_set(match); return ary; } while (!NIL_P(result = scan_once(str, pat, &start))) { match = rb_backref_get(); rb_match_busy(match); rb_yield(result); str_mod_check(str, p, len); rb_backref_set(match); /* restore $~ value */ } rb_backref_set(match); return str; }