-4

JSON と JavaScript に基づいて DSL を作成していますが、キー値を「生」で指定し、文字列区切り記号で囲まないようにする必要があります。うまくいけばこれを説明する簡単な例:

{myKey:custom_function('arg1'), myKey2:custom_function("another arg1")}

なるべき

{myKey:"custom_function('arg1')", myKey2:"custom_function(\"another arg1\")"}

これは、JSON オブジェクトの解析時に custom_function が存在しないためです。値を評価せずに JSON を解析できるようにする必要があり、キーを反復するときに値を 1 つずつ展開するだけです。

1 番目のスニペットを 2 番目のスニペットに変換するには、どの正規表現またはその他の方法を使用できますか?

より単純なソリューションで 90% のケースをカバーできると思いますが、防弾実装を作成するには多くの労力が必要です。私が行った JavaScript の正規表現サポート (明らかに後読み機能はありません) に関する調査に基づいて、1 行または 2 行以上の正規表現パターンが必要になると想定しています。

また、これはノード アプリケーション用であるため、このためのトリックも役に立ちます。

編集:

この質問にはいくつかの反対票が寄せられているようですが、将来のグーグル社員/私自身の参考のために、とにかく残しました。この種の問題にどの方法/手法が最適かについての完全に有効な質問であり、同様の問題に直面する他のノード/js 新規参入者が簡単に存在する可能性があります。

4

1 に答える 1

0

最終的な答え: 正規表現は、これほど複雑なタスクには適していません。私がオンラインで見つけた同様に複雑なソリューション (コード コメントの削除など) はすべて、正規表現を控えめに使用するだけで、主にカスタムの反復アプローチに頼っていたため、同様のアプローチはこの状況ではあまり苦痛ではありませんでした。

したがって、最終的に私が見つけた「最良の」方法は、問題に適したノードまたは他の場所からの正規表現や特殊なライブラリをあまり必要としませんでした。

最後に、同様の問題を抱えている可能性のある将来のグーグル社員のために、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("");
}
于 2012-05-04T00:33:14.257 に答える