Это второй день моего участия в августовском испытании обновлений, подробности о мероприятии:Испытание августовского обновления
Регулярное расширение
Конструктор регулярных выражений
В ES5,RegExp
Есть два случая для параметров конструктора.
В первом случае параметр представляет собой строку, а второй параметр представляет собой модификатор (флаг) регулярного выражения.
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
Во втором случае аргумент является регулярным выражением, и в этом случае возвращается копия исходного регулярного выражения.
var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;
Однако в настоящее время ES5 не позволяет добавлять модификаторы со вторым параметром, иначе будет сообщено об ошибке.
var regex = new RegExp(/xyz/, 'i');
// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another
ES6 изменил это поведение. еслиRegExp
Первый параметр конструктора — это обычный объект, затем вы можете использовать второй параметр для указания модификатора. Кроме того, возвращаемое регулярное выражение игнорирует модификаторы исходного регулярного выражения и использует только новые указанные модификаторы.
new RegExp(/abc/ig, 'i').flags
// "i"
В приведенном выше коде модификатор исходного регулярного объектаig
, он будет заменен вторым параметромi
покрытие.
Обычный метод для строк
До ES6 у строковых объектов было 4 метода, которые могли использовать регулярные выражения:match()
,replace()
,search()
а такжеsplit()
.
ES6 вызывает все эти 4 метода внутри языкаRegExp
Метод экземпляра , чтобы все обычные методы были определены вRegExp
на объекте.
-
String.prototype.match
передачаRegExp.prototype[Symbol.match]
-
String.prototype.replace
передачаRegExp.prototype[Symbol.replace]
-
String.prototype.search
передачаRegExp.prototype[Symbol.search]
-
String.prototype.split
передачаRegExp.prototype[Symbol.split]
у модификатор
ES6 добавляет регулярные выраженияu
модификатор, означающий «режим Unicode», используемый для правильной обработки более чем\uFFFF
символы Юникода. То есть четырехбайтная кодировка UTF-16 обрабатывается правильно.
/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
В приведенном выше коде\uD83D\uDC2A
представляет собой четырехбайтовую кодировку UTF-16, представляющую один символ. Однако ES5 не поддерживает четырехбайтную кодировку UTF-16 и распознает ее как два символа, в результате чего вторая строка кода приводит кtrue
. Добавленu
После модификатора ES6 распознает его как символ, поэтому результатом первой строки кода будетfalse
.
После добавленияu
Модификаторы изменят поведение следующих регулярных выражений.
(1) Точечный символ
точка(.
) в регулярном выражении означает любой отдельный символ, кроме символа новой строки. Для кодовых точек больше, чем0xFFFF
Необходимо добавить символы Unicode, символ точки не распознается.u
модификатор.
var s = '𠮷';
/^.$/.test(s) // false
/^.$/u.test(s) // true
Приведенный выше код означает, что если вы не добавитеu
модификатор, регулярное выражение будет считать строку состоящей из двух символов, и совпадение не удастся.
(2) Представление символов Unicode
В ES6 добавлено использование фигурных скобок для представления символов Unicode, которые необходимо добавлять в регулярное выражение.u
модификатор для распознавания фигурных скобок, иначе он будет интерпретирован как квантификатор.
/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true
/\u{20BB7}/u.test('𠮷') // true
Приведенный выше код означает, что если вы не добавитеu
модификатор, не распознанный регулярным выражением\u{61}
Это обозначение считает, что это соответствует только 61 последовательномуu
.
(3) Квантификаторы
использоватьu
После модификатора все кванты будут правильно идентифицировать кодовую точку.0xFFFF
символы Юникода.
/a{2}/.test('aa') // true
/a{2}/u.test('aa') // true
/𠮷{2}/.test('𠮷𠮷') // false
/𠮷{2}/u.test('𠮷𠮷') // true
(4) Предопределенный режим
u
Модификаторы также влияют на предопределенные шаблоны, независимо от того, больше ли кодовых точек, чем0xFFFF
символы Юникода.
/^\S$/.test('𠮷') // false
/^\S$/u.test('𠮷') // true
код выше\S
— это предопределенный шаблон, который соответствует всем символам, не являющимся пробелами. только добавилu
модификатор, который правильно соответствует кодовым точкам больше, чем0xFFFF
символы Юникода.
Используя это, можно написать функцию, которая правильно возвращает длину строки.
function codePointLength(text) {
var result = text.match(/[\s\S]/gu);
return result ? result.length : 0;
}
var s = '𠮷𠮷';
s.length // 4
codePointLength(s) // 2
(5) я модификатор
Некоторые символы Unicode имеют разные кодировки, но очень похожие шрифты, например,\u004B
а также\u212A
все в верхнем регистреK
.
/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true
В приведенном выше коде не добавляйтеu
модификатор, он не распознает неканоническийK
персонаж.
(6) Побег
нетu
В случае модификаторов в регулярном выражении нет определенных экранов (например, экранов запятых).\,
) недействителен, а вu
Будет сообщено о режиме.
/\,/ // /\,/
/\,/u // 报错
В приведенном выше коде нетu
модификатор, обратная косая черта перед запятой недействительна, добавьтеu
Модификатор сообщает об ошибке.
RegExp.prototype.unicode Свойство
Добавлен обычный экземпляр объектаunicode
свойство, указывающее, установлено ли оноu
модификатор.
const r1 = /hello/;
const r2 = /hello/u;
r1.unicode // false
r2.unicode // true
В приведенном выше коде установлено регулярное выражение?u
модификатор, который можно изменить сunicode
свойства, чтобы увидеть.
у модификатор
Кромеu
модификаторы, ES6 также добавляет регулярные выраженияy
модификаторы, называемые «липкими» модификаторами.
y
Модификаторы работают сg
Подобно модификатору, это также глобальное совпадение, и следующее совпадение начинается со следующей позиции, где предыдущее совпадение было успешным. разница заключается в том,g
модификатор до тех пор, пока есть совпадение в оставшихся позициях, в то время какy
Модификатор гарантирует, что совпадение должно начинаться с первой оставшейся позиции, что означает «клей».
var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;
r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]
r1.exec(s) // ["aa"]
r2.exec(s) // null
В приведенном выше коде есть два регулярных выражения, одно из которых используетg
модификатор, другой используетy
модификатор. Каждое из этих двух регулярных выражений выполняется дважды.При первом выполнении оба ведут себя одинаково, а остальные строки_aa_a
. из-заg
У украшения нет требований к расположению, поэтому второе выполнение возвращает результат, иy
Модификатор требует, чтобы совпадение начиналось с головы, поэтому вернитеnull
.
Если вы измените регулярное выражение, чтобы убедиться, что заголовок каждый раз совпадает,y
Модификатор вернет результат.
var s = 'aaa_aa_a';
var r = /a+_/y;
r.exec(s) // ["aaa_"]
r.exec(s) // ["aa_"]
Каждый приведенный выше код совпадения начинается с заголовка оставшейся строки.
использоватьlastIndex
свойства, которые могли бы быть лучше объясненыy
модификатор.
const REGEX = /a/g;
// 指定从2号位置(y)开始匹配
REGEX.lastIndex = 2;
// 匹配成功
const match = REGEX.exec('xaya');
// 在3号位置匹配成功
match.index // 3
// 下一次匹配从4号位开始
REGEX.lastIndex // 4
// 4号位开始匹配失败
REGEX.exec('xaya') // null
В приведенном выше кодеlastIndex
свойство указывает, где начинается каждый поиск,g
Модификатор выполняет поиск в обратном направлении от этой позиции до тех пор, пока не будет найдено совпадение.
y
Модификаторы также подчиняютсяlastIndex
собственность, но требование должно быть вlastIndex
Совпадение было найдено в указанном месте.
const REGEX = /a/y;
// 指定从2号位置开始匹配
REGEX.lastIndex = 2;
// 不是粘连,匹配失败
REGEX.exec('xaya') // null
// 指定从3号位置开始匹配
REGEX.lastIndex = 3;
// 3号位置是粘连,匹配成功
const match = REGEX.exec('xaya');
match.index // 3
REGEX.lastIndex // 4
Фактически,y
Модификаторы неявно соответствуют флагам в заголовке^
.
/b/y.exec('aba')
// null
Поскольку приведенный выше код не может гарантировать совпадение заголовка, он возвращаетnull
.y
Дизайнерский замысел модификатора состоит в том, чтобы голова соответствовала логотипу.^
Оба действительны в глобальных матчах.
Ниже находится строковый объектreplace
Примеры методов.
const REGEX = /a/gy;
'aaxa'.replace(REGEX, '-') // '--xa'
В приведенном выше коде последнийa
Поскольку он не появится в голове следующего матча, он не будет заменен.
одинy
пара модификаторовmatch
метод, который может вернуть только первое совпадение, которое должно соответствоватьg
модификаторы для возврата всех совпадений.
'a1a2a3'.match(/a\d/y) // ["a1"]
'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]
y
Одним из применений модификаторов является извлечение токенов из строк,y
Модификаторы гарантируют, что между совпадениями не будет пропущенных символов.
const TOKEN_Y = /\s*(\+|[0-9]+)\s*/y;
const TOKEN_G = /\s*(\+|[0-9]+)\s*/g;
tokenize(TOKEN_Y, '3 + 4')
// [ '3', '+', '4' ]
tokenize(TOKEN_G, '3 + 4')
// [ '3', '+', '4' ]
function tokenize(TOKEN_REGEX, str) {
let result = [];
let match;
while (match = TOKEN_REGEX.exec(str)) {
result.push(match[1]);
}
return result;
}
В приведенном выше коде, если в строке нет недопустимых символов,y
модификатор сg
Результаты извлечения модификатора такие же. Однако, как только появляется недопустимый персонаж, они ведут себя по-разному.
tokenize(TOKEN_Y, '3x + 4')
// [ '3' ]
tokenize(TOKEN_G, '3x + 4')
// [ '3', '+', '4' ]
В приведенном выше кодеg
модификатор игнорирует недопустимые символы, в то время какy
Модификаторы этого не делают, что облегчает обнаружение ошибок.
Свойство RegExp.prototype.sticky
а такжеy
Модификаторы совпадают, ES6 имеет более обычные объекты-экземпляры.sticky
свойство, указывающее, установлено ли оноy
модификатор.
var r = /hello\d/y;
r.sticky // true
RegExp.prototype.flags Свойство
ES6 добавляет регулярные выраженияflags
свойство, которое возвращает модификатор регулярного выражения.
// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"
// ES6 的 flags 属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'
модификатор s: режим dotAll
В регулярных выражениях точка (.
) — это специальный символ, представляющий любой отдельный символ, за двумя исключениями. Один из них представляет собой четырехбайтовый символ UTF-16, который можно использовать сu
Модификатор разрешается; другой является символом конца строки.
Так называемый терминатор строки — это символ, обозначающий конец строки. Следующие четыре символа являются «разделителями строк».
- U+000A Новая строка (
\n
) - U+000D возврат каретки (
\r
) - Разделитель строк U+2028 (разделитель строк)
- Разделитель абзацев U+2029 (разделитель абзацев)
/foo.bar/.test('foo\nbar')
// false
В приведенном выше коде, потому что.
Несоответствие\n
, поэтому регулярное выражение возвращаетfalse
.
Однако часто нам нужно сопоставить любой отдельный символ, и есть обходной путь.
/foo[^]bar/.test('foo\nbar')
// true
В конце концов, это решение не очень интуитивно понятно, ES2018представлятьs
модификатор такой, что.
Может соответствовать любому одиночному символу.
/foo.bar/s.test('foo\nbar') // true
это называетсяdotAll
Режим, то есть точки представляют все символы. Следовательно, регулярные выражения также вводятdotAll
Свойство, которое возвращает логическое значение, указывающее, находится ли регулярное выражение вdotAll
модель.
const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');
re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'
/s
Модификаторы и многострочные модификаторы/m
Нет конфликта, когда они используются вместе,.
соответствует всем символам, а^
а также$
Соответствует началу и концу каждой строки.
ретроспективное утверждение
Регулярные выражения языка JavaScript поддерживают только просмотр вперед и отрицательный просмотр вперед, но не просмотр назад и отрицательный просмотр назад. Представлено в ES2018ретроспективное утверждениеV8 Engine версия 4.9 (Chrome 62) уже поддерживается.
«Первое утверждение» означает, чтоx
только вy
Передняя часть соответствует только и должна быть записана как/x(?=y)/
. Например, чтобы соответствовать только цифрам до знака процента, напишите/\d+(?=%)/
. «Упреждающее отрицательное утверждение» означает,x
только отсутствуетy
Передняя часть соответствует только и должна быть записана как/x(?!y)/
. Например, чтобы соответствовать только номерам, которые не предшествуют знаку процента, напишите/\d+(?!%)/
.
/\d+(?=%)/.exec('100% of US presidents have been male') // ["100"]
/\d+(?!%)/.exec('that’s all 44 of them') // ["44"]
Приведенные выше две строки, если вы поменяете регулярные выражения местами, не дадут того же результата. Кроме того, вы также можете видеть, что часть между скобками «прогнозируемого утверждения» ((?=%)
), не включается в возвращаемый результат.
Утверждение просмотра назад противоположно утверждению просмотра вперед,x
только вy
соответствовать только позже, должно быть записано как/(?<=y)x/
. Например, чтобы соответствовать только числам после знака доллара, напишите/(?<=\$)\d+/
. Отрицательное утверждение просмотра назад противоположно отрицательному утверждению просмотра вперед.x
только отсутствуетy
соответствовать только позже, должно быть записано как/(?<!y)x/
. Например, чтобы соответствовать только числам, которые не стоят после знака доллара, напишите/(?<!\$)\d+/
.
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"]
/(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"]
В приведенном выше примере заключенная в квадратные скобки часть «утверждения позади-за» ((?<=\$)
), также не включается в возвращаемый результат.
В следующем примере показана замена строки с использованием утверждения просмотра назад.
const RE_DOLLAR_PREFIX = /(?<=\$)foo/g;
'$foo %foo foo'.replace(RE_DOLLAR_PREFIX, 'bar');
// '$bar %foo foo'
В приведенном выше коде только после знака доллараfoo
будет заменен.
Реализация «утверждения просмотра назад» должна сначала соответствовать/(?<=y)x/
изx
, затем снова налево, совпадаяy
часть.这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。
Во-первых, сборка утверждения такая же, как результат нормальных условий.
/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"]
/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]
В приведенном выше коде нам нужно зафиксировать два групповых совпадения. Без «утверждения просмотра назад» первая скобка находится в жадном режиме, а вторая скобка может захватить только один символ, поэтому результат105
а также3
. В случае «утверждения за строкой», поскольку порядок выполнения справа налево, вторая скобка является жадным режимом, а первая скобка может захватить только один символ, поэтому результат1
а также053
.
Во-вторых, обратная косая черта для «утверждений просмотра назад», также в обратном порядке, должна быть помещена перед соответствующей скобкой.
/(?<=(o)d\1)r/.exec('hodor') // null
/(?<=\1d(o))r/.exec('hodor') // ["r", "o"]
В приведенном выше коде, если ссылка обратной косой черты в утверждении строки позади (\1
) после круглых скобок не получится совпадающий результат, его нужно поставить впереди. Потому что утверждение lookbehind сначала сканирует слева направо, находит совпадение, а затем возвращается и завершает обратную косую черту справа налево.
Класс свойств Unicode
ES2018 представлятьновый способ написания классов\p{...}
а также\P{...}
, что позволяет регулярному выражению соответствовать всем символам, соответствующим свойству Unicode.
const regexGreekSymbol = /\p{Script=Greek}/u;
regexGreekSymbol.test('π') // true
В приведенном выше коде\p{Script=Greek}
Указывает, что соответствует греческой букве, поэтому соответствуетπ
успех.
Классы свойств Unicode задают имена свойств и значения свойств.
\p{UnicodePropertyName=UnicodePropertyValue}
Для некоторых свойств можно указать только имя свойства или указать только значение свойства.
\p{UnicodePropertyName}
\p{UnicodePropertyValue}
\P{…}
да\p{…}
Обратное соответствие , т. е. совпадение символов, не удовлетворяющих условию.
Обратите внимание, что эти два типа действительны только для Unicode, поэтому обязательно добавляйте их при их использовании.u
модификатор. если не добавитьu
модификаторы, использование регулярных выражений\p
а также\P
Будет сообщено об ошибке, ECMAScript резервирует эти два класса.
Благодаря разнообразию свойств Юникода этот новый класс очень выразителен.
const regex = /^\p{Decimal_Number}+$/u;
regex.test('𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼') // true
В приведенном выше коде класс атрибута указывает соответствие всем десятичным символам.Вы можете видеть, что десятичные символы различных шрифтов будут успешно сопоставлены.
\p{Number}
Даже соответствует римским цифрам.
// 匹配所有数字
const regex = /^\p{Number}+$/u;
regex.test('²³¹¼½¾') // true
regex.test('㉛㉜㉝') // true
regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true
Ниже приведены некоторые другие примеры.
// 匹配所有空格
\p{White_Space}
// 匹配各种文字的所有字母,等同于 Unicode 版的 \w
[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// 匹配各种文字的所有非字母的字符,等同于 Unicode 版的 \W
[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// 匹配 Emoji
/\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu
// 匹配所有的箭头字符
const regexArrows = /^\p{Block=Arrows}+$/u;
regexArrows.test('←↑→↓↔↕↖↗↘↙⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩') // true
именованный групповой матч
Введение
Регулярные выражения используют круглые скобки для группового сопоставления.
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
В приведенном выше коде в регулярном выражении есть три набора скобок. использоватьexec
методом можно извлечь три набора совпадающих результатов.
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31
Одна из проблем с сопоставлением групп заключается в том, что значение каждого сопоставления групп не так просто увидеть, и можно использовать только числа (например,matchObj[1]
) ссылка, если порядок групп изменен, порядковый номер должен быть изменен при ссылке.
Введено ES2018именованный групповой матч(Именованные группы захвата) позволяет указать имя для каждого совпадения группы, которое легко читается в коде и на него легко ссылаться.
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // "1999"
const month = matchObj.groups.month; // "12"
const day = matchObj.groups.day; // "31"
В приведенном выше коде «соответствие именованной группы» заключено в круглые скобки, а «вопросительный знак + угловая скобка + имя группы» добавляется к заголовку шаблона (?<year>
), тогда ты можешьexec
метод возвращает результатgroups
Имя группы указано в свойстве. При этом числовой порядковый номер (matchObj[1]
) остается в силе.
Именованный набор совпадающих добавлен для каждого эквивалентного совпадающего идентификатора группы совпадения с целью облегчения описания. Если группа становится заказом, это не соответствует обработке изменения кода.
Если именованная группа не совпадает, то соответствующаяgroups
Свойства объекта будутundefined
.
const RE_OPT_A = /^(?<as>a+)?$/;
const matchObj = RE_OPT_A.exec('');
matchObj.groups.as // undefined
'as' in matchObj.groups // true
В приведенном выше коде именованная группаas
совпадений не найдено, тоmatchObj.groups.as
Стоимость свойстваundefined
,а такжеas
Эта кнопкаgroups
всегда присутствует.
Разрушение присваивания и подстановки
При сопоставлении именованных групп вы можете использовать деструктурирующее присваивание для присвоения переменных непосредственно из результата сопоставления.
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
one // foo
two // bar
При замене строк используйте$<组名>
Относится к именованным группам.
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
'2015-01-02'.replace(re, '$<day>/$<month>/$<year>')
// '02/01/2015'
В приведенном выше кодеreplace
Второй параметр — это строковый метод, а не регулярное выражение.
replace
Второй параметр метода также может быть функцией, и последовательность параметров функции следующая.
'2015-01-02'.replace(re, (
matched, // 整个匹配结果 2015-01-02
capture1, // 第一个组匹配 2015
capture2, // 第二个组匹配 01
capture3, // 第三个组匹配 02
position, // 匹配开始的位置 0
S, // 原字符串 2015-01-02
groups // 具名组构成的一个对象 {year, month, day}
) => {
let {day, month, year} = groups;
return `${day}/${month}/${year}`;
});
Сопоставление именованной группы добавляет последний параметр функции на основе оригинала: объект, состоящий из именованной группы. Этот объект может быть уничтожен и назначен непосредственно внутри функции.
Цитировать
Если вы хотите сослаться на «совпадение именованной группы» внутри регулярного выражения, вы можете использовать\k<组名>
письма.
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false
Числовые ссылки (\1
) остается в силе.
const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false
Оба синтаксиса цитирования также могут использоваться одновременно.
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>!\1$/;
RE_TWICE.test('abc!abc!abc') // true
RE_TWICE.test('abc!abc!ab') // false
Обычный индекс соответствия
В настоящее время не очень удобно получать начальную и конечную позиции обычного результата сопоставления. обычный экземплярexec()
метод, возвращаемый результат имеетindex
Атрибут, вы можете получить начальную позицию всего результата сопоставления, но если он включает сопоставление групп, получить начальную позицию сопоставления каждой группы будет сложно.
теперь естьПредложение этапа 3,дляexec()
Возвращаемый результат метода плюсindices
Атрибут, по этому атрибуту можно получить начальную и конечную позиции совпадения.
const text = 'zabbcdef';
const re = /ab/;
const result = re.exec(text);
result.index // 1
result.indices // [ [1, 3] ]
В приведенном выше примереexec()
метод возвращает результатresult
,этоindex
атрибут - это весь результат совпадения (ab
) исходное положение, а егоindices
Свойство представляет собой массив, а элементы представляют собой массив начальных и конечных позиций каждого совпадения. Поскольку регулярное выражение в этом примере не имеет группового соответствия, поэтомуindices
Массив имеет только один элемент, что указывает на то, что начальная позиция всего совпадения1
, конечное положение3
.
Обратите внимание, что начальная позиция включается в результат сопоставления, а конечная позиция не включается в результат сопоставления. Например, результат сопоставленияab
, являются первой и второй позициями исходной строки соответственно, тогда конечной позицией является третья позиция.
Если регулярное выражение содержит групповые совпадения, тоindices
Массив, соответствующий атрибуту, будет содержать несколько элементов, обеспечивающих совпадение начальной и конечной позиции каждой группы.
const text = 'zabbcdef';
const re = /ab+(cd)/;
const result = re.exec(text);
result.indices // [ [ 1, 6 ], [ 4, 6 ] ]
В приведенном выше примере регулярное выражение содержит групповое совпадение, тогдаindices
Массив атрибутов состоит из двух элементов, первый элемент — это весь результат совпадения (abbcd
), второй член — групповое совпадение (cd
) начальная и конечная позиции.
Ниже приведен пример сопоставления нескольких групп.
const text = 'zabbcdef';
const re = /ab+(cd(ef))/;
const result = re.exec(text);
result.indices // [ [1, 8], [4, 8], [6, 8] ]
В приведенном выше примере регулярное выражение содержит два групповых совпадения, поэтомуindices
Массив свойств состоит из трех элементов.
Если регулярное выражение содержит совпадение именованной группы,indices
Массив атрибутов также будет иметьgroups
Атрибуты. Свойство — это объект, из которого можно получить начальную и конечную позиции именованной группы.
const text = 'zabbcdef';
const re = /ab+(?<Z>cd)/;
const result = re.exec(text);
result.indices.groups // { Z: [ 4, 6 ] }
В приведенном выше примереexec()
метод возвращает результатindices.groups
Свойство - это объект, который обеспечивает подходящую группуZ
начальное и конечное положения.
Если групповое сопоставление получить не удалось,indices
Соответствующий член массива атрибутовundefined
,indices.groups
Соответствующий член объекта свойства такжеundefined
.
const text = 'zabbcdef';
const re = /ab+(?<Z>ce)?/;
const result = re.exec(text);
result.indices[1] // undefined
result.indices.groups['Z'] // undefined
В приведенном выше примере, поскольку групповое сопоставление не удалось, поэтомуindices
массив атрибутов иindices.groups
Члены группы, соответствующие объекту атрибута,undefined
.
String.prototype.matchAll()
Если регулярное выражение имеет несколько совпадений в строке, оно обычно используется сейчас.g
модификатор илиy
Модификаторы вынимаются один за другим в цикле.
var regex = /t(e)(st(\d?))/g;
var string = 'test1test2test3';
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match);
}
matches
// [
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"],
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"],
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
// ]
В приведенном выше кодеwhile
Обычное сопоставление каждого раунда выполняется в цикле, всего три раунда.
ES2020повысилсяString.prototype.matchAll()
метод для получения всех совпадений одновременно. Однако он возвращает итератор, а не массив.
const string = 'test1test2test3';
const regex = /t(e)(st(\d?))/g;
for (const match of string.matchAll(regex)) {
console.log(match);
}
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
В приведенном выше коде, посколькуstring.matchAll(regex)
Возвращается итератор, поэтому вы можете использоватьfor...of
Выйдите из цикла. Преимущество возврата итератора по сравнению с возвратом массива заключается в том, что если результат сопоставления представляет собой большой массив, итератор более эффективно использует ресурсы.
Преобразование итератора в массив очень просто, используйте...
оператор иArray.from()
метод подойдет.
// 转为数组的方法一
[...string.matchAll(regex)]
// 转为数组的方法二
Array.from(string.matchAll(regex))