繁体   English   中英

使用正则表达式将文本解析为对象

[英]Parsing text to object with regex

我正在使用API​​,该API以以下格式返回文本:

#start
#p 12345 foo
#p 12346 bar
#end
#start
#p 12345 foo2
#p 12346 bar2
#end

我的解析功能:

function parseApiResponse(data) {

    var results = [], match, obj;

    while (match = CST.REGEX.POST.exec(/(#start)|(#end)|#p\s+(\S+)\s+(\S+)/ig)) {

        if (match[1]) {           // #start
            obj = {};

        } else if (match[2]) {    // #end
            results.push(obj);
            obj = null;           // prevent accidental reuse 
                                  // if input is malformed

        } else {                  // #p something something
            obj[match[3]] = match[4];
        }
    }

    return results;
}

这会给我一个看起来像这样的对象列表:

[{ '12345': 'foo', '12346': 'bar'}, /* etc... */]

但是,如果一行的格式如下

#start
#p 12345
#p 12346 bar
#end

该行实际上是#p 12345\\n而我的match[4]将包含下一行的#p

如何调整样式以适应这种情况?

假设每行有一个#end #start#end#p元素,则可以使正则表达式意识到这一点,并添加一个附加的非捕获组以指示一行中的最后一个\\s+(\\S+)是可选的:

/(#start)|(#end)|#p\\s+(\\S+)(?:\\s+(\\S+))?$/igm

(?: ) :)表示“将其作为一个整体进行处理,但不要捕获其匹配的模式”(因此它不会在match创建元素)。 ? 该组后面的意思是“该组是可选的,可能与该模式中的任何内容都不匹配”。 其后的$m标志一起匹配行尾。

您还可以通过使用*而不是+量词来避免(?: ) :)欺骗,这意味着“匹配零次或多次”:将\\s+(\\S+)更改为\\s*(\\S*) 这样做的副作用是,数字和其后的数据之间的空格现在是可选的。

我将重写正则表达式并重构代码,如下所示:

while (match = CST.REGEX.POST.exec(/^#(start|end|p)(?:\s+(\d+)(?:[^\S\r\n]+([^\r\n]+))?)?$/igm)) {
  switch (match[1]) {
    case 'start':
      obj = {};
      break;
    case 'end':
      results.push(obj);
      obj = null;
      break;
    case 'p':
      obj[match[2]] = match[3];
      break;
  }
}

我喜欢在一个捕获组中捕获startendp ,因此可以在switch语句中使用它。 我在这里使用的正则表达式的版本更具区分性(期望#p后面的标记为数字)和更多的宽容(允许#p行上的最后一个标记包含任何非换行符空白,例如#p 1138 this is only a test )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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