sawa sawa - 7 months ago 9
Ruby Question

Where did the character go?

I matched a string against a regex:

s = "`` `foo`"
r = /(?<backticks>`+)(?<inline>.+)\g<backticks>/


And I got:

s =~ r
$& # => "`` `foo`"
$~[:backticks] # => "`"
$~[:inline] # => " `foo"


Why is
$~[:inline]
not
"` `foo"
? Since
$&
is
s
, I expect:

$~[:backticks] + $~[:inline] + $~[:backticks]


to be
s
, but it is not, one backtick is gone. Where did the backtick go?

Answer

It is actually expected. Look:

  • (?<backticks>`+) - matches 1+ backticks and stores them in the named capture group "backticks" (there are two backticks). Then...
  • (?<inline>.+) - 1+ characters other than a newline are matched into the "inline" named capture group. It grabs all the string and backtracks to yield characters to the recursed subpattern that is actually the "backticks" capture group. So,...
  • \g<backticks> - finds 1 backtick that is at the end of the string. It satisfies the condition to match 1+ backticks. The named capture "backtick" buffer is re-written here.

The matching works like this:

"`` `foo`"
 ||1
   | 2 |
       |3

And then 1 becomes 3, and since 1 and 3 are the same group, you see one backtick.

Comments