gsub
gsub(*args)
public
Returns a copy of str with all occurrences of pattern substituted for the second argument. The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. ‘\d’ will match a backslash followed by ‘d’, instead of a digit.
If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern’s capture groups of the form \d, where d is a group number, or \k<n>, where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash. However, within replacement the special match variables, such as $&, will not refer to the current match.
If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.
In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $‘ will be set appropriately. The value returned by the block will be substituted for the match on each call.
The result inherits any tainting in the original string or any supplied replacement string.
When neither a block nor a second argument is supplied, an Enumerator is returned.
"hello".gsub(/[aeiou]/, '*') #=> "h*ll*" "hello".gsub(/([aeiou])/, '<\1>') #=> "h<e>ll<o>" "hello".gsub(/./) {|s| s.ord.to_s + ' '} #=> "104 101 108 108 111 " "hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') #=> "h{e}ll{o}" 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
Interpolating
Note that to interpolate, the sequences must be inside single quotes:
# replace /ll/ with itself 'hello'.gsub(/ll/, '\0') # returns 'hello' 'hello'.gsub(/ll/, "\0") # returns 'he\000o'
Replacing with "\" and match — a simple solution
A somewhat different approach to the same problem:
v.gsub(/(?=\W)/, '\\') #=> Foo\ Bar\!
But from what you are trying to achieve I suspect you might be interested in Regexp.escape method :)
Replacing with "\" and match
If you’re trying to place a “" in front of your matches, you’ll quickly see that it is a pain in the ass to add the quoting in the replacement string.
Here’s an example:
v = "Foo Bar!" # Target: Foo\ Bar\! # Resulting strings will not be quoted to decrease # the amount of backslashes. Compare \\! to "\\\\!" v.gsub(/\W/, '\0') #=> Foo Bar! # \\ escapes to a literal \, which next to the 0 becomes \0 v.gsub(/\W/, '\\0') #=> Foo Bar! # \\\0, means "\ \0", or "escaped \0" v.gsub(/\W/, '\\\0') #=> Foo\0Bar\0 # Same mechanism as before. \\ → \ v.gsub(/\W/, '\\\\0') #=> Foo\0Bar\0 # Finally! We have now an escaped \ before \0 and # we get the results we want. v.gsub(/\W/, '\\\\\0') #=> Foo\ Bar\! # It's very tempting to just write it like this now, right? v.gsub(/\W/) { |m| "\\#{m}" } #=> Foo\ Bar\! # It might not be shorter, but anyone can understand it.
Surely, there must be an easier way to do this. I haven’t found it, though. Hopefully, this makes it easier for you to understand why it behaves the way it does. :-)
Working with match captures
Let’s say you wanted to filter out passwords from:
s = "password=bob&password=jim&password=jane"
You’d do this:
r = /password\=([^\&]+)/ s.gsub!(r) { |m| m.gsub!($1, "[FILTERED]") }
Which would return
password=[FILTERED]&password=[FILTERED]&password=[FILTERED]
RE: Replacing with "\" and match — a simple solution
Thanks. No, I am not trying to quote for a regex. It was mostly an approach thing since I came into contact with the behavior previously when I played around. After doing some tests, I figured I should spare any other adventurers that part. :-)