JavaScript:避免使用String.split的空字符串和正则表达式优先级

时间:2013-11-11 23:36:37

标签: javascript regex split tokenize

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

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

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

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

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

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

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

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

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

是否有解决这些问题的方法?

2 个答案:

答案 0 :(得分:17)

使用lookahed来避免空匹配:

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

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

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

答案 1 :(得分:1)

通常,为了进行标记,您使用的是match,而不是split

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

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