最终答案:正则表达式不适合像这样复杂的任务。我在网上找到的任何类似复杂的解决方案(例如删除代码注释)都采用了主要是自定义的迭代方法,仅少量使用正则表达式,因此在这种情况下,类似的方法最终不会太轻松。
所以最后我能找到的“最佳”方法并没有涉及太多的正则表达式或节点或其他适合该问题的任何专门库。
最后,为了将来可能遇到类似问题的谷歌用户的利益,我在https://gist.github.com/2590689上发布了我的解决方案并复制如下:
//clothe a hub file that has 'naked' expressions
//e.g. turn {key:$('body p')} into {key:"$('body p')"}
function clothe(contents){
closers = /[\}\]\)\/"']/
openers = /[\{\[\(\/"']/
closing = {
"{": "}",
"[": "]",
"(": ")",
"/": "/",
'"': '"',
"'": "'"
}
contents = contents.split("");
var beforeKey = true;
var inKey = false;
var beforeValue = false;
var inValue = false;
var inArray = false;
var delimiterStack = [];
function inDelimited(){
return delimiterStack.length > 0;
}
function toggleDelimiter(d){
if(openers.exec(d) && !closers.exec(d)){
pushDelimiter(d);
}else if(openers.exec(d) && closers.exec(d)){
if(topDelimiter()){
if(topDelimiter()==d){
popDelimiterIfValid(d);
}else{
pushDelimiter(d);
}
}else{
pushDelimiter(d);
}
}else if(closers.exec(d)){
popDelimiterIfValid(d);
}
}
function topDelimiter(){
if(delimiterStack.length>=0){
return delimiterStack[delimiterStack.length-1];
}else{
return undefined;
}
}
function pushDelimiter(d){
delimiterStack.push(d);
}
function popDelimiterIfValid(d){
if(delimiterStack.length>0)
if(closing[delimiterStack[delimiterStack.length-1]]==d)
delimiterStack.pop(d);
}
function rTrimmedRightBound(rightBound){
while(rightBound>0){
if(!/\s/g.exec(contents[--rightBound])){
return rightBound+1;
}
}
}
for(var i=0; i<contents.length; i++){
function delimiterCheck(c){
if(c=='"'){
toggleDelimiter('"');
contents.splice(i, 0, '\\');
i++;
}else if(openers.exec(c) || closers.exec(c)){
toggleDelimiter(c)
}
}
if(beforeKey){
if(/[a-zA-Z0-9$_!]/.exec(contents[i])){
beforeKey = false;
inKey = true;
}
}else if(inKey){
if(contents[i]==":"){
inKey = false;
beforeValue = true;
}
}else if(beforeValue){
if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){
contents.splice(i, 0, '"');
i++;
beforeValue = false;
inValue = true;
delimiterCheck(contents[i]);
}else if(/\{/.exec(contents[i])){
beforeKey = true;
beforeValue = false;
}else if(/\[/.exec(contents[i])){
beforeValue = false;
inArray = true;
}
}else if(inArray && !inValue){
if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){
contents.splice(i, 0, '"');
i++;
beforeValue = false;
inValue = true;
delimiterCheck(contents[i]);
}
}else if(inValue){
if(!inDelimited() && /[\},\]]/.exec(contents[i])){
contents.splice(rTrimmedRightBound(i), 0, '"');
i++;
inValue = false;
if(/\]/.exec(contents[i])){
inArray = false;
}
beforeKey = !inArray;
}else{
delimiterCheck(contents[i]);
}
}
}
return contents.join("");
}