简体   繁体   中英

Replace single quotes, but not if within double quotes to use JSON.parse()

I need a solution to only exchange pairs of single quotes , which are NOT within a pair of double quotes .

A simplified example (original is > 100 KB):

['Element1',"Element's2",{"Element3":"E3"},'Element4']

In this example Element's2 should not become Element"s2 , but 'Element1' should become "Element1" .

Background: I need to extract some website data contained in big Javascript blocks. To get it i need JOSN.parse() which does not accept single quotes (') as quotes.

but i can not simply use replace(/'/g, '"') , because the single quote is also used as apostrophe in some texts like: "that's it" .

BTW: As @hakre recommenced, a much more simple solution for my case was to use eval() instead of JOSN.parse() . With eval() there was no need to exchange the single quotes.

I made a second variant, which also cares about escaped quotes like: [\\'Element1\\',"Element's2",{"Elements3":"E3"},'Element\\'s4']

but it is a bit slower and the code looks a bit more complicated (so i use the other variant):

 function convert(input) { var openQuote var close = {symbol:null,level:0,firstPos:null} openQuote = close; const singleQuote = "'" const doubleQuote = '"' const replaceBy = '"' var pairCount = 0 var data = Array.from(input) function replacePair(data, newChar, firstPos, secondPos) { data[firstPos] = newChar; data[secondPos] = newChar; pairCount++ } function checkEscaped (data, pos, level = 0) { if (pos <= 0) return level if (data[pos-1] == "\\\\") { return checkEscaped(data,pos-1,level+1) } return level } function checkQuotes(data,pos){ if (data[pos] == singleQuote) { let level = checkEscaped(data, pos) if (openQuote.symbol == null) {openQuote = {symbol: singleQuote, level: level, firstPos: pos}; return} if (openQuote.symbol == singleQuote && openQuote.level == level) {replacePair(data,replaceBy,openQuote.firstPos,pos); openQuote = close; return;} return } if (data[pos] == doubleQuote) { let level = checkEscaped(data, pos) if (openQuote.symbol == null) {openQuote = {symbol: doubleQuote, level: level, firstPos: pos}; return} if (openQuote.symbol == doubleQuote && openQuote.level == level) {openQuote = close; return;} } } for (let i=0; i < data.length; i++) { checkQuotes(data,i) } var result = data.join(""); console.log(pairCount , "Pairs of Single Quotes exchanged") return result } document.getElementById('start').addEventListener('click', () => { var dataIn = document.getElementById('input').value; var output = document.getElementById('output').value = convert(dataIn) });
 <html><body> <button id="start">start</button><BR> Input:<br><textarea id="input" name="w3review" rows="2" cols="100" spellcheck="false"> [\\'Element1\\',"Element's2",{"Elements3":"E3"},'Element\\'s4'] </textarea><BR> Output:<br><textarea id="output" name="w3review" rows="2" cols="100" spellcheck="false"></textarea> </body></html>

I have build this script to solve my problem. Even if is downvoted, this one works for my case and is a bit more fast.

 function convert(input) { const singleQuote = "'" const doubleQuote = '"' const replaceBy = '"' var firstSingleQuote = null var firstDoubleQuote = null var pairCount = 0 var data = Array.from(input) function replacePair(data, newChar, firstPos, secondPos) { data[firstPos] = newChar; data[secondPos] = newChar; pairCount++ } function checkQuotes(data,pos){ if (data[pos] == singleQuote) { if (firstSingleQuote == null && firstDoubleQuote == null) { firstSingleQuote = pos; return; } if (firstSingleQuote != null && firstDoubleQuote == null) { replacePair(data,replaceBy,firstSingleQuote,pos); firstSingleQuote = null; return; } if (firstSingleQuote == null && firstDoubleQuote != null) { return; } if (firstSingleQuote != null && firstDoubleQuote != null) { return; } } if (data[pos] == doubleQuote) { if (firstDoubleQuote == null && firstSingleQuote == null) { firstDoubleQuote = pos; return; } if (firstDoubleQuote != null && firstSingleQuote == null) { firstDoubleQuote = null; return; } // todo: replace doubleQuote if wanted!! if (firstDoubleQuote == null && firstSingleQuote != null) { return; } if (firstDoubleQuote != null && firstSingleQuote != null) { return; } } } for (let i=0; i < data.length; i++) { checkQuotes(data,i) } var result = data.join(""); console.log(pairCount , "Pairs of Single Quotes exchanged") return result } document.getElementById('start').addEventListener('click', () => { var dataIn = document.getElementById('input').value; var output = document.getElementById('output').value = convert(dataIn) });
 <html><body> <button id="start">start</button><BR> Input:<br><textarea id="input" name="w3review" rows="2" cols="100" spellcheck="false"> ['Element1',"Element's2",{"Element3":"E3"},'Element4'] </textarea><BR> Output:<br><textarea id="output" name="w3review" rows="2" cols="100" spellcheck="false"></textarea> </body></html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM