I thought I knew regexes pretty well, but this has me puzzled:
irb(main):016:0> source = "/foo/bar"
irb(main):017:0> source.gsub( /[^\/]*\Z/, "fubar" )
You need to use
sub as you only need to replace once at the end of the string:
source.sub( /[^\/]*\Z/, "fubar" ) ^^^
See the IDEONE demo
The problem is most probably with the way the matches are collected, and since you pattern matches an empty string, although at the end, the last null can also be treated as a 2nd match. It is not only a Ruby issue, a similar bug is present in many other languages.
So, actually, this is what is happening:
barand replaces it with
[^\/]*\Zmatches the NULL, and adds another
If you need to use
* quantifier that allows matching 0 characters with
+ that requires at least 1 occurrence of the quantified subpattern, avoid matching 0-length strings:
source.gsub( /[^\/]+\Z/, "fubar" ) ^
The rule of thumb: Avoid regexps that match empty strings inside Regex replace methods!