我正在使用带有多个定界符的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' ]
,这加强了我的思想,因为<=
是第一个指定的分隔符。
我搜索了一整堆,找不到这种行为的解释。分隔符如何分割工作?
非常感谢
答案 0 :(得分:2)
在大多数正则表达式引擎中,当您有多个可以匹配同一字符串的替代项时,它将使用第一个匹配的字符串。因此,无论您写的是<|<=
还是<=|<
。
如果输入字符串为foo<=bar
,则第一个版本将仅匹配<
,因为它是第一个匹配的替代,而第二个版本将匹配<=
。
这在Regular-Expression.info中有更详细的解释。
因此,通常的解决方案是按长度递减的顺序(例如,使用z.split(/(<=|<|=)/)
有些正则表达式引擎总是尝试找到最长的匹配项,而不是第一个匹配项(上面的页面称它们为“文本定向”)。但是JavaScript不会这样做。
答案 1 :(得分:1)
此处的替代顺序很重要。如果您在/(<|=|<=)/
上进行拆分,则它将在第一个匹配项上拆分,即找到<
。这意味着剩余的字符串不再具有该<=
,而仅具有=
,因此在该字符串上再次拆分。如果更改顺序,则可以确保<=
和<
之前分别匹配=
:
let z = 'c4 <= v4';
console.log(z.split(/(<=|=|<)/))
/(=|<=)/
的情况更加有趣,因为它与<=
相匹配。
let z = 'c4 <= v4';
console.log(z.split(/(=|<=)/))
之所以这样,是因为正则表达式引擎渴望匹配。扫描字符串时,它看到的第一个潜在匹配是<
。此时,它知道它与<=
替代项有潜在的匹配,因此如果继续到下一个字符以查看它是否实际上是匹配项。事实证明如此,它继续前进并考虑了比赛。不需要单独测试=
。
如果您使用类似以下的内容,则可以避免所有这些情况:/([<=]+)/
但这将更加宽容并匹配<
和=
的任意组合
let z = 'c4 <= v4 == x4 =< z6 = a9 < b9';
console.log(z.split(/([<=]+)/g))