У меня была задача разделить строку на две группы символов.
Итак, '031745'
→ [03,17,45]
Я применил подход regex и успешно справился с этим:
'031745'.split(/(?=(?:..)+$)/);
// result: ["03", "17", "45"]
Я знаю, что происходит здесь: мы пытаемся разделить невидимое место, которое имеет последующие группы из 2 символов, неоднократно.
Но есть две вещи, которые мне трудно объяснить:
1.
Если я удалю end
char $
, я получаю этот результат:
'031745'.split(/(?=(?:..)+)/);
// result: ["0", "3", "1", "7", "45"]'
Почему удаление $
влияет на результат? В конце концов, мы просто ищем повторяющиеся - не перекрывающиеся два символа.
2.
Почему меняется внутренняя группа на не захваченную группу, что приводит к другому результату:
'031745'.split(/(?=(..)$)/);
// result: ["0317", "45", "45"]
AFAIK - захваченные группы предназначены для обратной ссылки и для захвата группы. В конце концов, это повторяется повторяющаяся группа из двух символов, поэтому что делает (..)
поведение в этом конкретном случае иначе, чем (?:..)
?
nb, я знаю, что есть другие подходы, но все же я хочу остаться с Regex - целью обучения.
Почему удаление $ влияет на результат?
$
Гарантирует, что конец строки возникает после некоторого количества повторений двух символов. В противном случае местоположения, которые будут split
будут представлять собой любое местоположение, после которого есть как минимум два символа - это каждое местоположение (кроме только до конца строки). Таким образом, $
требуется для правильной строки. Когда есть некоторое количество символов между некоторой позицией и концом строки, вы хотите, чтобы regex терпит неудачу, так что (например) символы 0 и 1 не разделяются, а символы 2 и 3 не разделяются, и так далее.
Почему меняется внутренняя группа на не захваченную группу, что приводит к другому результату
Когда вы используете группу захвата внутри split
, все, что было захвачено, будет включено в результирующий массив в качестве дополнительного элемента, в дополнение к той части строки, которая split
до и после. Например:
console.log('foobar'.split(/(bar)/));
Здесь строка разделяется на bar
. Без группы захвата это приведет к ['foo', '']
:
console.log('foobar'.split(/(?:bar)/));
Но поскольку bar
был захвачен, он добавил между ними. То же самое происходит в вашем
'031745'.split(/(?=(..)$)/);
Поскольку окончательный 45
захвачен, он включается в результат из-за того, что он находится в группе захвата, но поскольку 45
находится внутри смотрового окна, он не потребляется в split
. Таким образом, 45
снова включены в результат из-за разрыва строки в месте между 0317
и 45
.
[
"0317", // Initial portion of the string
"45", // Captured group
"45" // Final portion of the string
]
match
короче:'031745'.match(/../g)
.