Feature #12745


String#(g)sub(!) should pass a MatchData to the block, not a String

Added by herwin (Herwin W) over 5 years ago. Updated 7 months ago.

Target version:


A simplified (and stupid) example: replace some placeholders in a string with function calls

def placeholder(val)
  raise 'Incorrect value' unless val == 'three'

str = '1.2.[three].4'
str.gsub!(/\[(\w+)\]/) { |m| placeholder(m) }

This raises the 'incorrect value' because we don't pass the match 'three', but the full string '[three]'. It looks like we have 3 options to fix that:

  1. Match [three] instead of three in the placeholder replacement method
  2. Pass m[1..-2] instead of m to the method (or strip it in placeholder)
  3. Use $1 in the method call, ignore the value that's passed to the block

Options 1 and 2 look kind of code duplication to me (and they're possible in the simplified example, but might get tricky in real situations). I don't like option 3 because you completely ignore the value that's been passed to the block in favor of global variables, you can't use named captures, and writing code this way makes it incompatible with Rubinius.

I think it would be more logical to pass a MatchData (like what you'd get with String#match) instead of a String to the block. The #to_s returns the whole string, so in 90% of the use cases the code could remain unaltered, but the remaining 10% makes it a change that shouldn't be backported to 2.3.

Attached is a very naive patch to pass a matchdata to the block called by String#sub. The additional change in rbinstall.rb was required to run make install, which actually shows an incompatiblity (which I hadn't anticipated)


ruby_string_sub_matchdata.diff (952 Bytes) ruby_string_sub_matchdata.diff herwin (Herwin W), 09/09/2016 06:32 PM

Related issues 4 (3 open1 closed)

Related to Ruby master - Feature #6802: String#scan should have equivalent yielding MatchDataAssignedmatz (Yukihiro Matsumoto)Actions
Related to Ruby master - Feature #5749: new method String#match_all neededAssignedmatz (Yukihiro Matsumoto)Actions
Related to Ruby master - Feature #5606: String#each_match(regexp)FeedbackActions
Related to Ruby master - Feature #546: String#gsub と Strnig#scan のブロックパラメータの一致Rejectedmatz (Yukihiro Matsumoto)09/06/2008Actions

Also available in: Atom PDF