JavaScript неправильно разбивает строку - PullRequest
1 голос
/ 14 февраля 2020

Согласно ECMA-262 §21.1.3.19 String.prototype.split ,

String.prototype.split ( separator, limit )

Возвращает Объект массива, в который были сохранены подстроки результата преобразования этого объекта в строку. Подстроки определяются путем поиска слева направо на предмет наличия разделителей; эти вхождения не являются частью какой-либо подстроки в возвращаемом массиве, но служат для разделения значения 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;'
]

Что здесь происходит? Как мне написать, чтобы соответствовать "мужчинам" или "предзнаменованиям"?


Окружение:

~ $ 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 ]

4 голосов
/ 14 февраля 2020

String.prototype.split spe c также говорит (в том же абзаце):

Значение разделителя может быть строкой любой длины или может быть объектом, таким как RegExp, который имеет метод @@ split.

Если мы посмотрим на spe c для 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 /));

Или для лучшей производительности , поскольку вы чередуете только отдельные символы, используйте класс символов:

let s = new String("All the world's a stage, And all the men and women merely players;");
console.log(s.split(/[ o]men /));
2 голосов
/ 14 февраля 2020

String.prototype.split ()

При обнаружении разделитель удаляется из строки, а подстроки возвращаются в массив.

Если разделитель является регулярным выражением с захватными скобками , то при каждом совпадении разделителя результаты (включая любые неопределенные результаты) захватывающих скобок вставляются в выходной массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...