Search code examples
regexruby

Applying string functions to Regexp in gsub in Ruby


In Python it's possible to do something like this:

re.sub("_.", lambda match: match.group().upper(), "ab_cde")

This would result in "ab_Cde", since the matched group is being upper'd.

Is there a way to achieve this in gsub in Ruby? I've tried "abcde".gsub(/_./, '\1'.upcase) but that just returns abcde unchanged.


Solution

  • See substitution methods docs

    These methods perform substitutions:

    • String#sub: One substitution (or none); returns a new string.

    • String#sub!: One substitution (or none); returns self.

    • String#gsub: Zero or more substitutions; returns a new string.

    • String#gsub!: Zero or more substitutions; returns self.

    Each of these methods takes:

    • A first argument, pattern (string or regexp), that specifies the substring(s) to be replaced.

    • Either of these:

      • A second argument, replacement (string or hash), that determines the replacing string.

      • A block that will determine the replacing string.

    Block

    In the block form, the current match string is passed to the block; the block’s return value becomes the replacing string

    It means you can do it this way

    # With usual block parameter
    "ab_cde".sub(/_./) { |match| match.upcase } # => "ab_Cde"
    "ab_cde".gsub(/_./) { |match| match.upcase } # => "ab_Cde"
    
    # With numbered block parameter (Ruby >= 2.7)
    "ab_cde".sub(/_./) { _1.upcase } # => "ab_Cde"
    "ab_cde".gsub(/_./) { _1.upcase } # => "ab_Cde"
    

    Be careful with bang-methods, they can return nil if there wasn't replacement