Here is a sample javascript function:
function quote(s) { s = s.replace(/^\s+|\s+$/g, ''); s = s.replace(/^"*|"*$/g, '"'); return s; }
The two lines of the function are intended to do the following:
For example, the string Hello world
should come out as "Hello world"
, and the string "Oh wow"
should come out unmodified; etc.
Unfortunately, as highlighted in this question on StackOverflow, it doesn't quite behave as expected. The combination of zero or more [characters] followed by the end-of-string and the global regular expression parameter to String.prototype.replace combine in an unfortunate edge case where the machinery of the regular expression engine and replacement algorithm must be understood before the behaviour can be predicted.
Put simply, "Oh wow"
comes out as "Oh wow""
Thom Blake provided the following explanation, which I will copy verbatim. Click to show the explanation below:
Essentially: because there is no actual "end-of-string token" the regular expression engine can't consume the $
, and because the String.prototype.replace function relies on explicitly falling off the end of the string, our function:
Note that it's not because we're replacing quotes with quotes; it's only because we're matching against zero or more [something] at the end of the string and finding "more" and then "zero".
So unfortunately there is no way to use a single regexp replacement to achieve our goal. A working solution is to remove all quotation marks from the string, and then affix a pair. This has the added advantage of santising the string, and ensuring matched quotation marks.
function quote(s) { s = s.replace(/^\s+|\s+$/g, ''); s = s.replace(/^"+|"+$/g, ''); s = '"' + s + '"'; return s; }
Examples: [src]
"
it should acquire a double-XX
at the endX
s at the start and end of the string with more clicksApparently Ruby's regular expression engine behaves the same way:
irb(main):001:0> 'foo'.gsub(/\A#*|#*z/, '#') => "#foo#" irb(main):002:0> '#foo'.gsub(/\A#*|#*\z/, '#') => "#foo#" irb(main):003:0> '##foo'.gsub(/\A#*|#*\z/, '#') => "#foo#" irb(main):004:0> 'foo#'.gsub(/\A#*|#*\z/, '#') => "#foo##" irb(main):005:0> 'foo##'.gsub(/\A#*|#*\z/, '#') => "#foo##" irb(main):006:0> '##foo##'.gsub(/\A#*|#*\z/, '#') => "#foo##"