如果指定了多个分隔符,javascript 的拆分函数如何通过分隔符工作



我正在使用带有多个分隔符的Javascript的split函数来分割字符串。虽然我让它工作,但它的行为让我感到困惑

下面有这个字符串--

let z = 'c4 <= v4';

我把它和console.log(z.split(/(<|=|<=)/))分开。该字符串可能包含<=<=,这就是我用3个分隔符对其进行拆分的原因。这给了我[ 'c4 ', '<', '', '=', ' v4' ],这不是我所期望的。我期待[ 'c4 ', '<=', ' v4' ]

然后我认为split在分隔符列表中向下移动,所以它首先由<分割,然后由=分割结果,这将解释<和=。然后,当它到达分隔符<=时,它在结果中找不到任何分隔符。

为了证明我的想法,我尝试了console.log(z.split(/(=|<=)/))。根据我的逻辑,我希望结果是[ 'c4 <', '=', ' v4' ],因为我希望split首先使用=作为分隔符。然而,实际结果是[ 'c4 ', '<=', ' v4' ]。几乎就像split跳过了分隔符=一样。

如果我安排分隔符console.log(z.split(/(<=|<|=)/))的顺序,我可以让它正确工作,并且会得到[ 'c4 ', '<=', ' v4' ],这在某种程度上强化了我的想法,因为<=是指定的第一个分隔符。

我搜索了一大堆,却找不到对这种行为的解释。如何通过分隔符进行拆分?

提前感谢

在大多数正则表达式引擎中,当有多个替换项可以匹配同一字符串时,它会使用第一个匹配项。所以写<|<=还是<=|<是有区别的。

如果输入字符串是foo<=bar,则第一个版本将只匹配<,因为它是匹配的第一个备选方案,而第二个版本将匹配<=

Regular-Expression.info.对此有更详细的解释

因此,通常的解决方案是按照长度递减的顺序编写带有备选项的正则表达式,例如z.split(/(<=|<|=)/)

有些正则表达式引擎总是试图找到最长的匹配项,而不是第一个匹配项(上面的页面称它们为"文本定向")。但JavaScript并不能做到这一点。

候补的顺序在这里很重要。如果在/(<|=|<=)/上进行拆分,它将在找到的第一个匹配即<时进行拆分。这意味着剩下的字符串不再具有<=,它只具有=,因此它再次在此基础上进行拆分。如果您更改订单,您可以确保<=<=之前匹配:

let z = 'c4 <= v4';
console.log(z.split(/(<=|=|<)/))

/(=|<=)/的情况更有趣,因为它与<=匹配。

let z = 'c4 <= v4';
console.log(z.split(/(=|<=)/))

这是因为正则表达式引擎急切地匹配。在扫描字符串时,它看到的第一个潜在匹配是<。在这一点上,它知道它与<=备选方案有潜在的匹配,所以if继续到下一个字符,看看它是否真的匹配。事实证明是这样的,它继续前进,并认为这是一场比赛。它从不需要单独测试=

如果你使用更像/([<=]+)/的东西,你可以避免所有这些,但这将更宽容,并匹配<=的任何组合

let z = 'c4 <= v4 == x4 =< z6 = a9 < b9';
console.log(z.split(/([<=]+)/g))