When using regular expressions in Ruby, what is the difference between $1 and \1?
+13
A:
\1 is a backreference which will only work in the same sub
or gsub
method call, e.g.:
"foobar".sub(/foo(.*)/, "\1\1") # => "barbar"
$1 is a global variable which can be used in later code:
if "foobar" =~ /foo(.*)/ then
puts "The matching word was #{$1}"
end
(prints "The matching word was bar")
Avdi
2008-11-13 22:37:04
+6
A:
Keep in mind there's a third option, the block form of sub
. Sometimes you need it. Say you want to replace some text with the reverse of that text. You can't use $1 because it's not bound quickly enough:
"foobar".sub(/(.*)/, $1.reverse) # WRONG: either uses a PREVIOUS value of $1,
# or gives an error if $1 is unbound
You also can't use \1
, because the sub
method just does a simple text-substitution of \1
with the appropriate captured text, there's no magic taking place here:
"foobar".sub(/(.*)/, '\1'.reverse) # WRONG: returns '1\'
So if you want to do anything fancy, you should use the block form of sub
($1, $2, $`, $' etc. will be available):
"foobar".sub(/.*/){|m| m.reverse} # => returns 'raboof'
"foobar".sub(/(...)(...)/){$1.reverse + $2.reverse} # => returns 'oofrab'
Brian Carper
2008-11-13 23:01:17
Your example could be misleading - the match is what's passed to the block, not the matchgroups. So, if you wanted to change "foobar" to "foorab", you'd have to do `str.sub(/(foo)(\w+)/) { $1 + $2.reverse }`
rampion
2008-11-14 05:21:52
rampion
2008-11-14 05:22:30
Right, I'll edit to clear it up.
Brian Carper
2008-11-14 18:41:15
You saved my day!
Adrian
2008-11-15 22:02:02