When using regular expressions in Ruby, what is the difference between $1 and \1?
Asked
Active
Viewed 2.7k times
2 Answers
82
\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
Output:
"The matching word was bar"
# => nil
-
Note that [Ruby's treatment of single vs double quotes](http://stackoverflow.com/a/3028799/303896) can get in your way when trying to use backreferences. – alxndr May 13 '16 at 22:29
-
didn't understand much, can someone please provide some more explanation – YasirAzgar Apr 25 '17 at 07:28
-
@YasirAzgar `.sub()` is a method call. `'\1'` can (apparently) only be used within the scope of a `sub` or `gsub` method call. In the first example, `"foobar".sub(/foo(.*)/, '\1\1')`, `'\1'` is within the scope of the `sub` method. In the second example, `$1` is referenced outside of a `sub` / `gsub` method. The example shows it referenced shortly after a `=~` call, but that's irrelevant. Apparently, the use of a regex sets `$1`, which, as a global variable, can be referenced anywhere. – John Dec 30 '17 at 16:27
-
Also FYI, apparently `$1` is not a true global variable. In ruby, creating a variable that begins with `$` makes it a global variable (but apparently `$1` is special and is not actually a global variable). The intricacies of the `$1` variable are, apparently, not officially documented. This [S.O. question](https://stackoverflow.com/a/18550606/5490505) kinda touches upon `$1` – John Dec 30 '17 at 16:56
-
[Ruby docs](https://ruby-doc.org/core-2.4.2/Regexp.html#class-Regexp-label-Special+global+variables) has some more info on the special regexp globals. "These global variables are thread-local and method-local variables." – John Dec 30 '17 at 17:54
-
**NB:** you must use single quotes (as in `'\1'`) **or** you must use a double backslash in double quotes (as in `"\\1"`). – GDP2 Oct 05 '18 at 17:30
30
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
- 71,150
- 28
- 166
- 168
-
1Your 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 Nov 14 '08 at 05:21
-
1See ri String#sub: 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. – rampion Nov 14 '08 at 05:22