3

我的目标是解析具有特定格式的字符串以从中生成 javascript 对象结构。

一个想法是使用带有函数的String.replace作为参数。所以在函数中你得到了比赛的所有部分。到目前为止我的测试/示例:

字符串:

    !Norm: DIN 7985;
        M2: 2, 2, 2;
        M3:3,3;
        M10: 20,25;
!Norm: DIN 7985 TX;
    M4: 4,  4    , 4;

我的测试代码:

console.clear();
var sTmp = "!Norm: DIN 7985;\n    M2: 2, 2, 2;\n    M3:3,3;\n    M10: 20,25;\n     !Norm: DIN 7985 TX;\n    M2: 6,    10    , 16;";
//console.log(sTmp);

function replacer(match, p1, p2, p3, p4, offset, string){
    //console.log("-");
    console.log("match:", match);
    console.log("p1:", p1);
    console.log("p2:", p2);
    console.log("p3:", p3);
    console.log("p4:", p4);
    console.log("offset:", offset);
    console.log("string:", string);
    return "#";
}
//(?=!Norm:\s?(.+);\s+)
sTmp.replace(/\s*!Norm:\s?(.+);\s+(M\d+:.*\s*;)/g, replacer);

(在萤火虫中测试)控制台日志(缩短):

match: !Norm: DIN 7985; M2: 2, 2, 2;
p1: DIN 7985
p2: M2: 2, 2, 2;
p3: 0
p4: !Norm: DIN 7985; M2: 2, 2, 2; M3:3,3; M10: 20,25; ....
offset: undefined
string: undefined
match: !Norm: DIN 7985 TX; M4: 4, 4 , 4;
p1: DIN 7985 TX
p2: M4: 4, 4 , 4;
p3: 52
p4: !Norm: DIN 7985; M2: 2, 2, 2; M3:3,3; M10: 20,25; !Norm: DIN 7985 TX; M4: 4, 4 , 4;
....

所以我可以看到这个想法是可行的——它符合规范,我在一个子字符串中得到了信息。现在有 M3:... 零件。那么是否有一个选项可以指定该部分(M\d+:.*\s*;)匹配下一个 !Norm: 而不是 ; 第一次出现?我认为它应该可以通过前瞻或其他方式实现?

这个想法背后的目标是从字符串中生成一个像这样的javascript对象:

    oDataTmp = {
    DIN 7985 :      {
                        M2        : ["2", "2", "2"],
                        M3        : ["3", "3"],
                        M10       : ["20", "25"],
                    }
    DIN 7985 TX :   {
                        M4        : ["4", "4", "4"],
                    }
}

我知道你可以通过拆分来做到这一点,然后逐行解析。我喜欢完成这个大脑任务并了解如何去做的挑战:-)

4

3 回答 3

2

这是我的正则表达式:

\s*!\w+:\s*([^;]+);\s*((?:\s*[^:!]+:[^;]+;)+)

它具有以下匹配组:

  • 第 1 组:DIN 部分。
  • 第 2 组:当前 !Norm 的所有剩余设置。

此正则表达式并不特别期望关键字 NORM。所以它可能是其他任何东西。如果要捕获它,只需在第一个 \w+ 周围添加括号。

解释:

/            # start regex
\s*          # match optional whitespace
!\w+:        # match word between '!' and ':'
\s*          # match optional whitespace
([^;]+);     # capture group 1 - match all characters (without ';') up to the next ';'
\s*          # match optional whitespace
(            # start capture group 2
    (?:          # group (non-capture)
        \s*          # match optional whitespace
        [^:!]+:      # match all characters (without ':' and '!') up to the next ':'
        [^;]+;       # match all characters (without ';') up to the next ';'
    )+           # group end; match this group 1 to n times
)            # end capture group 2
/g           # end regex; set g-Flag for global
于 2012-11-27T17:59:20.403 回答
1

您需要更改两件事以使所有成员都成为一次捕获。首先.不匹配换行符(你不能在 JavaScript 中改变它)。但[\s\S]确实如此。是的,使用负前瞻,我们可以确保我们不消耗下一个!Norm

/\s*!Norm:\s?(.+);\s+((?:(?![!]Norm)[\s\S])*)/g

我已将文字!放在方括号中,以明确它是文字并将其!与负前瞻语法的一部分分开。您可以省略方括号,这只是为了便于阅读。所以基本上这将用任意字符填充最后一次捕获,只要它们不开始一个新的!Norm.

然后您可以继续,从最后一次捕获中读取各个属性和值。

解释:

/            # start regex
\s*          # match optional whitespace
!Norm:       # match '!Norm:'
\s?          # match optional whitespace
(.+);        # capture group 1 - match all characters (whitout '\n') up to the next ';'
\s+          # match 1..n whitespaces
(            # start capture group 2
    (?:          # group (non-capture)
        (?!          # negative lookahead
            [!]Norm      # match '!Norm'
        )            # end negative lookahead
        [\s\S]       # match a white space or other than white space character
                     # this group match a single character as long as it dont start are new !Norm
    )*           # group end; match this group 0..n times
)            # end capture group 2
/g           # end regex; set g-Flag for global
于 2012-11-27T17:21:45.307 回答
0

所以在这里有一个完整的解决方案,我解析使用的正则表达式的洞来自两个答案的组合:

console.clear();
var sData = "!Norm: DIN 933;\n !Norm: DIN 7985;\n    M2: 2, 2, 2;\n    M3:3,3;\n    M10: 20,25;\n     !Norm: DIN 7985 TX;\n    M2: 6,    10    , 16;";
console.log(sTmp);

var oData = {};

// Parse sData with help of Regex replace
sData.replace(/\s*!Norm:\s*([^;]+);\s*((?:(?![!]Norm)[\s\S])*)/g, 
    function replacer(match, sNorm, sScrews, offset, string) {
        //console.log("match:", match);
        //console.log("sNorm:", sNorm);
        //console.log("sScrews:", sScrews);
        //console.log("offset:", offset);
        //console.log("string:", string);

        var oScrews = {};

        sScrews.replace(/\s*(M\d+):\s*([^;]+);\s*/g, 
            function(match, sScrewSize, sScrewList, offset, string) {
                //console.log("match:", match);
                //console.log("sScrewSize:", sScrewSize);
                //console.log("sScrewList:", sScrewList);
                //console.log("offset:", offset);
                //console.log("string:", string);

                oScrews[sScrewSize] = sScrewList.split(/[\s,]+/);

                return "§";
            });

        oData[sNorm] = oScrews;

        return "#";
    });

console.log("oData: ");
console.dir(oData);

结果对象(在控制台中验证):

oData = {
    DIN 7985 :      {
                        M10 : ["20", "25"],
                        M2  : ["2", "2", "2"],
                        M3  : ["3", "3"],
                    }
    DIN 7985 TX :   {
                        M4  : ["4", "4", "4"],
                    }
    DIN 933 :       {}
    };
于 2012-11-27T21:32:21.717 回答