JavaScript:避免使用String.split和正则表达式优先级的空字符串
我正在创建一个语法高亮显示,并使用String.split从输入字符串创建标记。 第一个问题是String.split会创建大量的空字符串,这会导致一切都比其他情况下慢得多 例如,JavaScript:避免使用String.split和正则表达式优先级的空字符串,javascript,regex,split,tokenize,Javascript,Regex,Split,Tokenize,我正在创建一个语法高亮显示,并使用String.split从输入字符串创建标记。 第一个问题是String.split会创建大量的空字符串,这会导致一切都比其他情况下慢得多 例如,“***”。拆分(/(\*)/)->[“”、“*”、“”、“*”、“”、“*”、“”]。 有没有办法避免这种情况 另一个问题是正则表达式本身的表达式优先级。 假设我试图解析一个C风格的多行注释。 也就是说,/*注释*/。 现在,让我们假设输入字符串是“/*****/”。 如果我使用下面的正则表达式,它会工作,但会产生很
“***”。拆分(/(\*)/)
->[“”、“*”、“”、“*”、“”、“*”、“”]
。
有没有办法避免这种情况
另一个问题是正则表达式本身的表达式优先级。
假设我试图解析一个C风格的多行注释。
也就是说,/*注释*/
。
现在,让我们假设输入字符串是“/*****/”
。
如果我使用下面的正则表达式,它会工作,但会产生很多额外的标记(以及所有那些空字符串!)
更好的方法是读取/*
,*/
,然后在一个令牌中读取所有剩余的*
。
也就是说,上述字符串的更好结果是[“/*”、“***”、“*/”]
。
然而,当使用正则表达式时,我得到了不好的结果。
正则表达式是这样的:/(\/\*\*\*\/\*+)/
但是,此表达式的结果是:[“/*”、“***”、“/”]
。
我猜这是因为最后一部分是贪婪的,所以它从另一部分偷走了火柴
我找到的唯一解决方案是生成一个否定的前瞻表达式,如下所示:
/(\/\*|\*\/|\*+(?!\/)/
这给出了预期的结果,但与另一个相比速度非常慢,这对大字符串有影响
这些问题有解决方案吗?使用lookahed避免空匹配:
arr = "***".split(/(?=\*)/);
//=> ["*", "*", "*"]
arr = "***".split(/(\*)/).filter(Boolean);
//=> ["*", "*", "*"]
或者使用过滤器(布尔值)
放弃空匹配:
arr = "***".split(/(?=\*)/);
//=> ["*", "*", "*"]
arr = "***".split(/(\*)/).filter(Boolean);
//=> ["*", "*", "*"]
通常,对于标记化,您使用
match
,而不是split
:
> str = "/****/"
"/****/"
> str.match(/(\/\*)(.*?)(\*\/)/)
["/****/", "/*", "**", "*/"]
还要注意非贪婪修饰符
?
是如何解决第二个问题的。很遗憾,前瞻不允许我在同一个令牌中获取多个东西,例如上面示例中的一个令牌“***”。我以前使用过filter(),但是额外的数组遍历实际上使整个代码比跳过空字符串进行一次迭代时的速度慢。Anu--很抱歉打扰您,但是您能解释一下或给我指出一个解释.filter(布尔)概念的资源吗。空字符串是否返回为false等。。我对您的用法有点困惑。空字符串在布尔表达式中计算为false。arr=“***.”split(“”);也可用于标记字符串中的单个字符。@anubhava您正在回答7年前的一个答案:)我不记得当时我做了什么,但最终用正则表达式标记并不是最好的,最好为您想要的任何输入创建一个特定的标记器(例如,逐字符迭代并知道标记何时开始/结束),它比regexisi am标记化巨大字符串要快得多,效率也更高,C风格的多行注释只是一个例子,该regex如何适应其余部分?(其余部分是{}()[]+-/&^=!等等)。与此同时,我刚刚停止使用贪婪修饰符获取所有*,而其余的令牌确实使用它。最糟糕的情况是当有许多*,但由于它们通常不多,我想我可以接受。作为记录,这是我目前的正则表达式:/[\t]+\[+\\[+\\]+\\\{+\\\\\+\\\+\\\+\\{+\\\\\\\+\\\\+\\(+\\)+|\++|\-+|\*|\/+|+|&+|\|+|=+|!+|\\/
@user2503048:好吧,javascript中有很多语法亮点,也许你可以从研究它们的源代码开始?你的regexp看起来不太理想。“****”.split().join().split(”);我知道这可能不是你需要的。但似乎很有效。