11

我正在创建一个语法荧光笔,我正在使用 String.split 从输入字符串创建标记。第一个问题是 String.split 创建了大量的空字符串,这导致一切都比原本可能的要慢得多。

例如,"***".split(/(\*)/)-> ["", "*", "", "*", "", "*", ""]。有没有办法避免这种情况?

另一个问题是正则表达式本身的表达式优先级。假设我正在尝试解析 C 风格的多行注释。即,/* comment */。现在让我们假设输入字符串是"/****/". 如果我要使用以下正则表达式,它会起作用,但会产生很多额外的标记(以及所有那些空字符串!)。

/(\/\*|\*\/|\*)/

一种更好的方法是读取/*'s, */'s,然后*在一个标记中读取所有其余的 's。也就是说,上述字符串的更好结果是["/*", "**", "*/"]. 但是,当使用应该执行此操作的正则表达式时,我会得到不好的结果。正则表达式是这样的:/(\/\*|\*\/|\*+)/.

然而,这个表达式的结果是这样的:["/*", "***", "/"]. 我猜这是因为最后一部分是贪婪的,所以它从另一部分窃取了比赛。

我找到的唯一解决方案是制作一个否定的前瞻表达式,如下所示:

/(\/\*|\*\/|\*+(?!\/)/

这给出了预期的结果,但与另一个相比它非常慢,这对大字符串有影响。

有没有解决这些问题的方法?

4

2 回答 2

20

使用lookahed避免空匹配:

arr = "***".split(/(?=\*)/);
//=> ["*", "*", "*"]

或用于filter(Boolean)丢弃空匹配:

arr = "***".split(/(\*)/).filter(Boolean);
//=> ["*", "*", "*"]
于 2013-11-11T23:42:29.860 回答
2

通常用于标记您使用match,而不是split

> str = "/****/"
"/****/"
> str.match(/(\/\*)(.*?)(\*\/)/)
["/****/", "/*", "**", "*/"]

还要注意非贪婪修饰符如何?解决第二个问题。

于 2013-11-12T00:38:21.870 回答