Javascript 用不包含在括号()中的冒号拆分字符串
我正在开发一个HTML5/JavaScript游戏引擎,我开始遇到一个过去从未遇到过的场景,我不知道如何才能实现这一点 简单地说,我想通过一个字符将一个字符串拆分成一个数组,只要该字符不在括号内 基本上,在诸如items/tile之类的XML文件中,我存储“triggers”,即为代码将执行的操作提供规则的语句。单个触发器的不同参数用冒号(:)分隔,一个项可以有多个触发器,每个触发器用逗号分隔。下面是一个例子:Javascript 用不包含在括号()中的冒号拆分字符串,javascript,regex,arrays,split,Javascript,Regex,Arrays,Split,我正在开发一个HTML5/JavaScript游戏引擎,我开始遇到一个过去从未遇到过的场景,我不知道如何才能实现这一点 简单地说,我想通过一个字符将一个字符串拆分成一个数组,只要该字符不在括号内 基本上,在诸如items/tile之类的XML文件中,我存储“triggers”,即为代码将执行的操作提供规则的语句。单个触发器的不同参数用冒号(:)分隔,一个项可以有多个触发器,每个触发器用逗号分隔。下面是一个例子: <response trigger="npc:self:dialog:1:3"
<response trigger="npc:self:dialog:1:3">No, thank you.</response>
<response trigger="shop:open:1:(npc:self:dialog:1:4)">Yes, please.</response>
不用了,谢谢。
(这基本上是说:如果选择了此响应,则使提出初始问题的NPC循环成为特定转换的特定消息)
继续:我需要能够将回调触发器封装在带有特定触发器的参数括号内。下面是一个例子:
<response trigger="npc:self:dialog:1:3">No, thank you.</response>
<response trigger="shop:open:1:(npc:self:dialog:1:4)">Yes, please.</response>
好的。
(这基本上是说:打开一个特定的商店,当商店关闭时,跳转到一个特定的对话/信息,供正在讲话的NPC使用)
其思想是,当一个存储被关闭时,我可以调用该触发器的第四个参数(即触发器本身)。正如我确信您已经猜到的,这里的问题是,如果我根据“:”分割初始触发器字符串,那么它会将回调触发器分解为主触发器的其他(混乱的)参数。我不想那样。我也不想做任何事情,比如用另一个角色拆分辅助触发器(出于以后的世代原因,并且因为我想有时我会想在更深的层次上嵌套许多触发器,我不想使用不同的字符。我知道解决方法,但我想学习如何正确地拆分不包含在其他特定字符中的字符
因为我用括号封装回调参数,所以我认为必须有一个干净的正则表达式,我可以使用它将主触发器字符串按括号以外的所有冒号拆分
遗憾的是,我还没能想出正确的表达方式来完成这个任务
有什么想法吗
我非常感谢你们中的任何一位可能得到的任何帮助。有一个很好的理由可以解释为什么你们找不到解决问题的正则表达式: 您描述的语言是非正则的,即不能用正则表达式解析 基本上,为了确定所有括号之外的冒号,必须解析括号结构。这在正则表达式中是不可能的 嵌套括号的语言是上下文无关的[1],因此编写递归解析器非常简单 [1] 另外:您不需要递归解析器,括号嵌套级别的简单计数器就足够了:
// Pseudo code
int depth = 0;
List<int> breakIndices;
for int index = 0 .. input.length-1:
switch(input[index])
':': if (depth==0) breakIndices.add(index); break;
'(': depth++; break;
')': depth--; break;
default: break;
// Now, all indices of the colons you need are in the breakIndices list.
//伪代码
int深度=0;
列出指数;
对于int index=0..input.length-1:
开关(输入[索引])
“:”:如果(深度==0)breakIndex.add(索引);break;
“(”:深度++;中断;
“)”:深度--;中断;
默认:中断;
//现在,您需要的冒号的所有索引都在breakindex列表中。
我想你不能,至少如果有嵌套括号的可能,因为识别正确的括号嵌套不是很正常
无论如何,不要构造一些巴洛克正则表达式,而是考虑一个非常简单的解析器:扫描下一个“或”(或)的下一个事件,并用下一个令牌做一些事情。重复。
parse(string)
if string is empty: return
scan to delimiter, put delimiter index into d, token string into t
put t into a table for processing later
case on d:
string[d] == ":": parseColonToken(string[d+1:])
string[d] == "(": parseParentString(strin[d+1:])
end
end
(显然这是伪代码。将string[n://code>作为“从索引n到末尾的string
的子字符串。)
考虑到这一点,您可能只需要从parseColonToken
开始,但我不确定这是否符合您的预期语法。我认为最简单的方法是将字符串分为“函数”部分和“参数”部分,然后分别处理这两部分。如果要保留参数部分的括号,则:
var parts1 = "shop:open:1:(npc:self:dialog:1:4)".split(/:(?=\()/);
// parts1 now looks like ["shop:open:1", "(npc:self:dialog:1:4)"]
var parts2 = "shop:open:1".split(/:(?=\()/);
// parts2 now looks like ["shop:open:1"]
然后:
var cmd = null;
var arg = null;
if(parts.length > 0) {
cmd = parts[0].split(':');
arg = (parts[1] || '').replace(/[()]/g, '').split(':');
}
你也许可以把更多的内容塞进一个正则表达式中(可能所有的内容都取决于你的目标正则表达式引擎支持的非常规功能),但是没有太多的意义,对你的代码来说,清晰是比“简短”更好的目标。任何看过上面内容的人都应该能够弄清楚如果他们手头有一个简单的代码,它在做什么
如果你最后处理的是更复杂的表达式,比如引号和转义之类的,那么你可以尝试修改来做你需要的事情。确定是否可以使用正则表达式解析的关键问题:括号可以嵌套吗?@cobbal:我会说是的,引号“我想有时候我会想在更深层次上嵌套很多触发器“@ChristianSemrau啊,我似乎错过了这一点。一个离题的建议:使用。你的生活会更轻松。@Zirak使用JSON在这里不会有任何区别-JSON只会取代XML作为结构容器,我正在处理的数据是一个字符串(并将继续如此)。如果我将触发器结构化为XML(出于各种原因,我不会这么说)那么它可能是相关的。我不同意JSON与XML之争;XML的额外膨胀对于一个乍一看结构上是人类可读的数据容器来说是一个很小的代价(特别是因为我现在手动编写这些数据文件).感谢您的洞察力和示例方法。我承认,也许我是一厢情愿的想法,一行就可以成功,所以我将使用您的示例(以及此处提供的另一个示例)我再次感谢你解释为什么这不是一个正则表达式的场景。事实上。但我不知道有前男友的证据