我有一个类型的字符串:
'??__HELLO__?? WORLD ##SAMPLE --MAIN--##'
我需要解析它并获取包含以下内容的数组:
[{ marker: '??', value: { marker: '__', value: 'HELLO' }, ' WORLD ', { marker: '##', value: ['SAMPLE ' , { marker: '--', value: 'MAIN' }]]
所以我有这个arkers:
this.markers = {
b: '??',
i: '##',
u: '__',
s: '--',
};
我有一个生成堆栈的函数:
parse(string) {
this.string = string;
this.stack = [];
for (let i = 0; i < string.length; i++) {
for (let marker of Object.values(this.markers)) {
if (string[i] + string[i + 1] === marker) {
this.stack.push({ marker: marker, index: i });
this.stack.push('');
i++;
break;
} else if (marker === Object.values(this.markers)[Object.values(this.markers).length - 1]) {
this.stack[this.stack.length - 1] = this.stack[this.stack.length - 1].concat(string[i]);
break;
}
}
}
for (let i = 0; i < this.stack.length; i++) {
if (this.stack[i] === '') {
this.stack.splice(i, 1);
i--;
}
}
console.log(this.stack);
return this.parseRecursively(this.stack[0]);
}
在我的示例中,堆栈将包含:
[ { marker: '??', index: 0 },
{ marker: '__', index: 2 },
'HELLO',
{ marker: '__', index: 9 },
{ marker: '??', index: 11 },
' WORLD ',
{ marker: '##', index: 20 },
'SAMPLE ',
{ marker: '--', index: 26 },
'MAIN',
{ marker: '--', index: 31 },
{ marker: '##', index: 33 } ]
此函数调用另一个递归生成输出数组的函数:
parseRecursively(element) {
if (this.stack.length === 0) {
return;
}
let parsed = [];
for (let i = this.stack.indexOf(element); i < this.stack.length; i++) {
if (typeof this.stack[i] === 'object') {
if (this.stack[i].marker === this.stack[this.stack.indexOf(this.stack[i]) + 1].marker) {
let popped = this.stack.splice(this.stack.indexOf(this.stack[i]) + 1, 1)[0];
let popped2 = this.stack.splice(this.stack.indexOf(this.stack[i]), 1)[0];
return { marker: popped.marker, value: this.string.substring(popped2.index + 2, popped.index) };
} else {
parsed.push({ marker: this.stack[i].marker, value: this.parseRecursively(this.stack[this.stack.indexOf(this.stack[i]) + 1]) });
i = -1;
}
} else {
parsed.push(this.stack.splice(this.stack.indexOf(this.stack[i]), 1)[0]);
i -= 2;
}
}
我尝试了上述函数的许多实现,但它仍然无法解析字符串。
那么我该如何重写这个功能呢?
谢谢!
P.S。只有普通的JavaScript,仅此而且我认为使用正则表达式将有助于更轻松地解决它,这里是我的正则表达式:
this.regex = /(\?{2}|#{2}|\-{2}|_{2})(.+?)(\1)/g;
答案 0 :(得分:1)
好的,经过一番思考,这是我对你的问题的看法:
function parse(str, markers = ['??', '__', '##', '--']) {
// Escape the markers (mostly useless...)
const e = markers.map(m => m.replace(/./g, '\\$&'))
// Create regexs to match each individual marker.
const groups = e.map(m => new RegExp('(' + m + ')(.*?)' + m));
// Create the regex to match any group.
const regex = new RegExp('(' + e.map(m => m + '.*?' + m).join('|') + ')');
const output = [];
// 'Match' the groups markers.
str = str.split(regex).filter(_ => _);
// Iterate over each of the split markers. e.g.
// From: '??__HELLO__?? WORLD ##SAMPLE --MAIN--##'
// To: ['??__HELLO__??', ' WORLD ', '##SAMPLE --MAIN--##']
return str.map(match => {
// Find the marker if it is a marker.
marker = groups.find(m => m.test(match));
// If it's not a marker return the value.
if (!marker) {
return match.trim();
}
// It is a marker so make the marker object.
match = match.match(marker);
return {
marker: match[1],
// Do the recursion.
value: parse(match[2], markers)
}
})
}
// Usage example:
console.log(
parse('??__HELLO__?? WORLD ##SAMPLE --MAIN--##')
);
.as-console-wrapper {min-height: 100%;}
此代码中使用的各个正则表达式以以下样式构建:
??
变为\?\?
\?\?
变为(\?\?)
(.*?)
(\?\?)(.*?)\?\?
这意味着默认的正则表达式数组如下所示:
[
/(\?\?)(.*?)\?\?/,
/(\_\_)(.*?)\_\_/,
/(\#\#)(.*?)\#\#/,
/(\-\-)(.*?)\-\-/
]
匹配任何标记正则表达式将如下所示:
/\?\?.*?\?\?|\_\_.*?\_\_|\#\#.*?\#\#|\-\-.*?\-\-/
实际上是相同的正则表达式,只是没有匹配的组。