我必须解析一个包含变量值对组的文档,这些变量值对被序列化为一个字符串,例如像这样:
4^26^VAR1^6^VALUE1^VAR2^4^VAL2^^1^14^VAR1^6^VALUE1^^
以下是不同的元素:
组ID:
4 ^ 26 ^ VAR1 ^ 6 ^ VALUE1 ^ VAR2 ^ 4 ^ VAL2 ^^的 1 ^ 14 ^ VAR1 ^ 6 ^ VALUE1 ^^
< / LI>每组的字符串表示长度:
4 ^的 26 ^ VAR1 ^ 6 ^ VALUE1 ^ VAR2 ^ 4 ^ VAL2 ^^ 1 ^的 14 ^ VAR1 ^ 6 ^ VALUE1 ^^
< / LI>其中一个小组:
4 ^ 26 ^ VAR1 ^ 6 ^ VALUE1 ^ VAR2 ^ 4 ^ VAL2 ^^ 1 ^ 14 ^ VAR1 ^ 6 ^ VALUE1 ^^
变量:
4 ^ 26 ^的 VAR1 ^ 6 ^ VALUE1 ^的 VAR2 ^ 4 ^ VAL2 ^^ 1 ^ 14 ^的 VAR1 ^ 6 ^ VALUE1 ^^
值的字符串表示长度:
4 ^ 26 ^ VAR1 ^的 6 ^ VALUE1 ^ VAR2 ^的 4 ^ VAL2 ^^ 1 ^ 14 ^ VAR1 ^的 6 ^ VALUE1 ^^
价值观本身:
4 ^ 26 ^ VAR1 ^ 6 ^的 VALUE1 ^ VAR2 ^ 4 ^的 VAL2 ^^ 1 ^ 14 ^ VAR1 ^ 6 ^的 VALUE1 ^^
变量仅由字母数字字符组成。
没有对这些值进行假设,即它们可能包含任何字符,包括^
。
这种语法有名字吗?是否有可以处理这个混乱的解析库?
到目前为止,我正在使用自己的解析器,但由于我需要检测并处理损坏的序列化,因此代码看起来相当混乱,因此我对解析器库的问题可以解除负担。
答案 0 :(得分:1)
最简单的方法是注意有两个嵌套级别以相同的方式工作。模式非常简单:
id^length^content^
在外层,这会产生一组组。在每个组中,content
遵循完全相同的模式,只有id
是变量名称,content
是变量值。
因此,您只需要编写一次该逻辑,然后可以使用它来解析这两个级别。只需编写一个将字符串分解为id
/ content
对列表的函数。调用它一次以获取组,然后循环遍历它们再次为每个content
调用它以获取该组中的变量。
将它分解为这些步骤,首先我们需要一种从字符串中获取“标记”的方法。此函数返回一个具有三种方法的对象,以查明我们是否处于“文件结尾”,并获取下一个分隔或计数的子字符串:
var tokens = function(str) {
var pos = 0;
return {
eof: function() {
return pos == str.length;
},
delimited: function(d) {
var end = str.indexOf(d, pos);
if (end == -1) {
throw new Error('Expected delimiter');
}
var result = str.substr(pos, end - pos);
pos = end + d.length;
return result;
},
counted: function(c) {
var result = str.substr(pos, c);
pos += c;
return result;
}
};
};
现在我们可以方便地编写可重用的解析函数:
var parse = function(str) {
var parts = {};
var t = tokens(str);
while (!t.eof()) {
var id = t.delimited('^');
var len = t.delimited('^');
var content = t.counted(parseInt(len, 10));
var end = t.counted(1);
if (end !== '^') {
throw new Error('Expected ^ after counted string, instead found: ' + end);
}
parts[id] = content;
}
return parts;
};
它构建一个对象,其中键是ID(或变量名)。我觉得它们的名字并不重要。
然后我们可以在两个级别使用它来创建完成整个工作的功能:
var parseGroups = function(str) {
var groups = parse(str);
Object.keys(groups).forEach(function(id) {
groups[id] = parse(groups[id]);
});
return groups;
}
对于您的示例,它会生成此对象:
{
'1': {
VAR1: 'VALUE1'
},
'4': {
VAR1: 'VALUE1',
VAR2: 'VAL2'
}
}
答案 1 :(得分:0)
我不认为为此创建语法是一项微不足道的任务。但另一方面,简单直接的方法并不难。您知道每个关键字符串的相应字符串长度。所以你只需按照那些长度分开你的字符串..
你在哪里看到问题?