提问人:Yk Music 提问时间:5/18/2023 最后编辑:Yk Music 更新时间:5/18/2023 访问量:49
Javascript 正则表达式:在不使用额外括号的情况下获取括号内的特定部分
Javascript Regex: get specific parts inside brackets without taking extra brackets
问:
我正在构建一个程序,可以简化编码不和谐机器人。我想添加内联函数,但似乎我的正则表达式选择器不是完美的匹配。
我的程序遍历每个内联函数,并测试它是否存在于字符串中。并将内联函数字符串替换为内联函数返回。
例如,{ping} 被转换为 91。或者,将 {id author} 转换为消息作者的 id。
问题在于,如果内联函数中有内联函数。我设法每 1 个解决 1 个内联函数,但随着数量的增长,我的正则表达式选择器失败了,只是匹配了错误的东西。
我希望它匹配什么:
{avatarurl {id {message}}}
^^^^^^^^^^^^^^
甚至可以匹配这一点:
{avatarurl {id {message}}}
^^^^^^^^^
这也是:
{avatarurl {id {message}}}
^^^^^^^^^^^^^^^^^^^^^^^^^^
等等。
它只需要从 {(function name) 开始并以 } 结尾。
我的正则表达式选择器无法匹配这部分,它只是匹配额外的括号。我需要一个完美的正则表达式选择器,它将匹配 {blabla},但在放入另一个 {blabla} 时仍然可以工作。
这是没有奏效的模式:new RegExp(`\{${func.name}([^\}]+[^])*\}`)
func.name 是函数名称。 我还需要“{funcname”之后和“}”之前的部分。
答:
2赞
blakkwater
5/18/2023
#1
这是括号的通用非正则表达式解决方案(支持非平衡输入)。
然后,您只需遍历树并搜索匹配项即可。
编辑:转换为类
class BracketTree {
constructor (brackets, string) {
if (typeof brackets != 'string' || brackets.length != 2 || brackets[0] == brackets[1]) {
return null;
}
let opening = brackets[0];
let closing = brackets[1];
function parse (start) {
let children = [];
let pos = start;
loop: while (pos < string.length) {
switch (string[pos]) {
case opening:
let child = parse(pos + 1);
children.push(child);
if (child.end == string.length) {
break loop;
}
pos = child.end;
break;
case closing:
if (start == 0) {
children = [{
children, start, end: pos, opened: false, closed: true,
contents: string.slice(0, pos)
}];
}
else {
return {
children, start, end: pos, opened: true, closed: true,
contents: string.slice(start, pos)
};
}
}
pos++;
}
return (start == 0)? {
children, start, end: string.length, opened: false, closed: false,
contents: string
}: {
children, start, end: string.length, opened: true, closed: false,
contents: string.slice(start)
};
}
this.root = parse(0);
}
traverse (callback) {
if (typeof callback != 'function') {
return false;
}
let root = this.root;
let input = root.contents;
let nodeId = 0;
function recurse (parent, level) {
function callbackLeaf (start, end) {
callback({
root, parent, level,
nodeId: nodeId++, childId: childId++,
start, end, contents: input.slice(start, end)
});
}
function callbackBranch (branch) {
return callback({
root, parent, branch, level,
nodeId: nodeId++, childId: childId++
});
}
let children = parent.children;
let childId = 0;
if (children.length == 0) {
callbackLeaf(parent.start, parent.end);
return;
}
callbackLeaf(parent.start, children[0].start - children[0].opened);
if (callbackBranch(children[0])) {
recurse(children[0], level+1);
}
for (var i = 0; i < children.length-1; i++) {
callbackLeaf(children[i].end + children[i].closed, children[i+1].start - children[i+1].opened);
if (callbackBranch(children[i+1])) {
recurse(children[i+1], level+1);
}
}
callbackLeaf(children[i].end + children[i].closed, parent.end);
}
recurse(root, 0);
return true;
}
}
let input = 'NOT OPENED {3}2}1}***{avatarurl {id {message}}} blah blah blah {1{2{3} NOT CLOSED';
let tree = new BracketTree('{}', input);
function filteredTraverse (caption, leafFilter, branchFilter) {
console.log(`${'-'.repeat(29 - caption.length/2)} ${caption} `.padEnd(60, '-'));
leafFilter ??= () => true;
branchFilter ??= () => true;
tree.traverse((args) => {
if (args.branch) {
return branchFilter(args);
}
if (leafFilter(args)) {
console.log(`${' '.repeat(args.level)}<${args.contents}>`);
}
});
}
filteredTraverse(
'Ignore unbalanced and all their descendants',
null,
({branch}) => branch.opened && branch.closed
);
filteredTraverse(
'Ignore unbalanced but include their descendants',
({parent}) => parent.opened == parent.closed
);
filteredTraverse(
'Ignore empty',
({start, end}) => start != end
);
filteredTraverse(
'Show non-empty first children only',
({childId, start, end}) => childId == 0 && start != end
);
上一个:如何将下划线视为空格提取文档编号
下一个:为什么正则表达式找不到匹配项
评论