JavaScript无法正确分割字符串

时间:2020-02-14 02:09:48

标签: javascript regex

根据ECMA-262 §21.1.3.19 String.prototype.split

String.prototype.split ( separator, limit )

返回一个Array对象,该对象已存储为将该对象转换为String的结果的子字符串。通过从左到右搜索是否出现分隔符来确定子字符串。 这些事件不是返回数组中任何子字符串的一部分,而是用于划分String值

但是,我目前正在观察一种奇怪的行为。这是代码:

let s = new String("All the world's a stage, And all the men and women merely players;");
console.log(s.split(/( |o)men /));

预期输出:

[
  "All the world's a stage, And all the",
  'and w',
  'merely players;'
]

实际输出:

[
  "All the world's a stage, And all the",
  ' ',
  'and w',
  'o',
  'merely players;'
]

这是怎么回事?我应该怎么写才能匹配“ men”或“ omen”?


环境:

~ $ node --version
v13.8.0

请注意:

Python3的行为相同。

import re
s = "All the world's a stage, And all the men and women merely players;"
print(re.compile("( |o)men ").split(s))
  #=> ["All the world's a stage, And all the", ' ', 'and w', 'o', 'merely players;']
print(re.compile("(?: |o)men ").split(s))
  #=> ["All the world's a stage, And all the", 'and w', 'merely players;']

对于这种奇怪的行为(至少对我来说),也许有合理的理由或实际用例...

2 个答案:

答案 0 :(得分:4)

String.prototype.split spec也说(在同一段中):

分隔符的值可以是任意长度的字符串,也可以是具有@@ split方法的对象,例如RegExp。

如果我们查看RegExp.prototype [ @@split ]的规范,它会说:

如果正则表达式包含捕获括号,则每次匹配分隔符时,捕获括号的结果(包括任何未定义的结果)都会被拼接到输出数组中。

这说明了您看到的行为。要解决此问题,只需使用非捕获组即可,即

let s = new String("All the world's a stage, And all the men and women merely players;");
console.log(s.split(/(?: |o)men /));

或者,for better performance,因为您只是交替使用单个字符,所以请使用字符类:

let s = new String("All the world's a stage, And all the men and women merely players;");
console.log(s.split(/[ o]men /));

答案 1 :(得分:2)

String.prototype.split()

找到后,从字符串中删除分隔符,并将子字符串返回到数组中。

如果分隔符是带有捕获括号的正则表达式,则每次分隔符匹配时,捕获括号的结果(包括任何未定义的结果)都会被拼接到输出数组中。