3

I wanted to change all the simple quotes ("…") of a string to smart quotes (“…”):

str.replace(/"/g,'“');

But then I realized that, in order to do it, I have to match the opening and closing quote, something like this:

str.replace(/REGEX_FOR_OPENING_QUOTES/g,'“');
str.replace(/REGEX_FOR_CLOSING)_QUOTES/g,'”');

What regex should I use in this case?

alexchenco
  • 53,565
  • 76
  • 241
  • 413
  • Not sure why you would do that, but -> https://gist.github.com/zerolab/1633661 – adeneo Jan 05 '15 at 05:39
  • @adeneo: That answer doesn't have JS specific solution. – anubhava Jan 05 '15 at 05:47
  • @anubhava - are you serious, I closed as a duplicate of this -> http://stackoverflow.com/questions/2202811/converting-straight-quotes-to-curly-quotes – adeneo Jan 05 '15 at 05:58
  • Yes that answer says: **For languages that don't support look-behind, like Javascript, as long as you replace all the front-facing ones first, you have two options:** Question is how to get all **front-facing ones first**? – anubhava Jan 05 '15 at 06:12
  • @anubhava - it's a javascript question with a javascript answer, actually 8 of them, where one is accepted. If you feel none of them answer the question, maybe you should close that one as a duplicate of this one. – adeneo Jan 05 '15 at 06:21
  • Yes that question is tagged as JavaScript but accepted answer doesn't have JS specific answer since it is using lookbehind which doesn't exist in JS. – anubhava Jan 05 '15 at 06:28

3 Answers3

2

This is a pretty naive approach which loops through every regular quote and toggles it between a smart open and close quote, but it may work for you...

function addSmartQuotes(str) {
  var open = false;
  return str.replace(/"/g, function(match, $1) {
    open = !open;
    return open ? '“' : '”';
  });
}

var str = 'This is my "string", blahdy "blah" blah';
console.log(addSmartQuotes(str)); // => This is my “string”, blahdy “blah” blah

It's also worth noting that unless you're sure that your page is in UTF-8, it's best to use HTML character codes for the open and closing quotes instead of the UTF-8 characters. These are “ (“) and ” (”).

alexpls
  • 1,914
  • 20
  • 29
  • `These are “ (“) and ” (”).` This is bad advice. HTML entities are not converted inside script tag. Use Unicode escape instead `\u201c` for the left quote, `\u201d` for the right quote. – nhahtdh Jan 05 '15 at 10:17
2

Another solution, if you need to make sure that " forms a pair and you assume that two nearest double quotes should be matched:

input.replace(/"([^"]*)"/g, "“$1”");

Example run:

'"test" dskfjsdfklds "sdfsdf" "'.replace(/"([^"]*)"/g, "“$1”");

Output:

“test” dskfjsdfklds “sdfsdf” "

(The last " is not converted, since it does not form a pair)

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
1

You can use lookahead based regex:

var s = 'abc "quoted string" foo bar "another quoted text" baz';
var r = s.replace(/"(?=(([^"]+"){2})*[^"]*"[^"]*$)/g, '<').replace(/"/g, '>');
//=> abc <quoted string> foo bar <another quoted text> baz

PS: Replace < and > by and .

Trick is to find " that is followed by odd number of " using this lookahead first: (?=(([^"]+"){2})*[^"]*"[^"]*$). Then remaining closing " can be replaced by .

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • not sure why everything was turned to the opening smart quote only. I did this `chapterString = chapterContent.replace(/"(?=(([^"]+"){2})*[^"]*"[^"]*$)/g, '“').replace(/"/g, '”')` and I got thing: `

    ”What?” My date`

    – alexchenco Jan 05 '15 at 07:02
  • I will post a jsfiddle demo link in few minutes after reaching back to my computer. – anubhava Jan 05 '15 at 07:18
  • Oh yes I realized that it's because I have stuff like this `

    "What?` and the code thinks it's a word. Okay, thanks a lot.

    – alexchenco Jan 05 '15 at 07:25
  • @alexchenco: I don't know why you are accepting this monstrous regex as accepted answer, while there is a simpler solution using replacement function below. – nhahtdh Jan 05 '15 at 10:14
  • @nhahtdh OK, I unchecked the answer. I'll wait for a while and see. – alexchenco Jan 05 '15 at 10:34
  • Monstrous regex really? This is fairly widely used regex pattern to detect even/odd # of quotes using pure regex solutions. – anubhava Jan 05 '15 at 10:46
  • @anubhava: It is "widely" used, but I don't think many people can read and understand such code, compared to the solution with replacement function. – nhahtdh Jan 05 '15 at 11:16
  • Shouldn't be hard to read for programmers familiar with lookahead. `replace` with callback function will also make it possible but that is not pure regex solution. It can also be done by using a simple loop for that matter. – anubhava Jan 05 '15 at 11:20
  • @anubhava: There is no need for a pure regex solution when the OP is using a programming language. The replacement function works well in this case without writing an explicit loop. These advanced regex should be reserved for when there is no other choice but a pure regex solution. – nhahtdh Jan 05 '15 at 11:28
  • It is just a matter of choice, I guess, many regex can be replaced by alternative programming code actually. IMHO a simple loop that reads input chat by char makes it most readable. – anubhava Jan 05 '15 at 11:32
  • @anubhava: See my answer for an alternate solution. – nhahtdh Jan 05 '15 at 11:33