В чем проблема с этим регулярным выражением при использовании глобального флага и флага, нечувствительного к регистру? Запрос - это пользовательский ввод. Результат должен быть [true, true].
var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
result.push(re.test('Foo Bar'));
// result will be [true, false]
var reg = /^a$/g;
for(i = 0; i++ < 10;)
console.log(reg.test("a"));
Объект RegExp
отслеживает lastIndex
, где произошло совпадение, поэтому в последующих матчах он будет начинаться с последнего использованного index, а не 0. Посмотрите:
var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
alert(re.lastIndex);
result.push(re.test('Foo Bar'));
Если вы не хотите, чтобы вручную reset lastIndex
до 0 после каждого теста, просто удалите флаг g
.
Здесь алгоритм, определяемый спецификациями (раздел 15.10.6.2):
RegExp.prototype.exec(строка)
Проводит соответствие регулярного выражения строки против регулярного выражения и возвращает объект Array, содержащий результаты матча, или null, если строка не соответствует Строка ToString (строка) выполняется поиск появление регулярного выражения шаблон следующим образом:
- Пусть S - значение ToString (string).
- Пусть длина - длина S.
- Пусть lastIndex - значение свойства lastIndex.
- Пусть я - значение ToInteger (lastIndex).
- Если глобальное свойство является ложным, пусть я = 0.
- Если я < 0 или I > length, то установите lastIndex равным 0 и верните null.
- Вызовите [[Match]], предоставив ему аргументы S и i. Если [[Match]] возвращенный отказ, перейдите к шагу 8; в противном случае r будет его результатом состояния и перейдите к шагу 10.
- Пусть я = я + 1.
- Перейдите к шагу 6.
- Пусть значение e равно значению endIndex.
- Если глобальное свойство истинно, установите lastIndex в e.
- Пусть n - длина массива r-захватов. (Это тоже самое значение как 15.10.2.1 NCapturingParens.)
- Возвращает новый массив со следующими свойствами:
- Индекс свойство устанавливается в положение согласованная подстрока в пределах полной строка S.
- Установлено свойство ввода к S.
- Свойство length имеет значение n + 1.
- Свойство 0 установлено на подстрокой (т.е. частью S между смещением я включительно и offset e exclusive).
- Для каждого целое число я такое, что I > 0 и я ≤ n, установите свойство с именем ToString (i) в i-й элемент массива r захватывает массив.
Вы используете один объект RegExp
и выполняете его несколько раз. При каждом последующем выполнении он продолжается от последнего индекса соответствия.
Вам нужно "reset" регулярное выражение начинать с начала перед каждым исполнением:
result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
// result is now [true, true]
Сказав, что может быть более читаемым каждый раз создавать новый объект RegExp (служебные данные минимальны, поскольку RegExp кэшируется в любом случае):
result.push((/Foo B/gi).test(stringA));
result.push((/Foo B/gi).test(stringB));
RegExp.prototype.test
обновляет свойство регулярных выражений lastIndex
, чтобы каждый тест начинался с остановки последнего. Я бы предложил использовать String.prototype.match
, поскольку он не обновляет свойство lastIndex
:
!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true
Примечание. !!
преобразует его в логическое, а затем инвертирует логическое значение, чтобы он отражал результат.
В качестве альтернативы вы можете просто reset свойство lastIndex
:
result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
Удаление глобального флага g
устраняет вашу проблему.
var re = new RegExp(query, 'gi');
Должно быть
var re = new RegExp(query, 'i');
У меня была функция:
function parseDevName(name) {
var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
var match = re.exec(name);
return match.slice(1,4);
}
var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");
Первый звонок работает. Второй звонок - нет. Операция slice
жалуется на нулевое значение. Я предполагаю, что это из-за re.lastIndex
. Это странно, потому что я ожидал бы, что новый RegExp
будет выделяться каждый раз, когда функция вызывается и не разделяется несколькими вызовами моей функции.
Когда я изменил его на:
var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');
Тогда я не получаю эффект lastIndex
holdover. Он работает так, как я ожидал.
Использование флага /g сообщает ему продолжить поиск после попадания.
Перед первым поиском:
myRegex.lastIndex
//is 0
После первого поиска
myRegex.lastIndex
//is 8
Удалите g и он выйдет из поиска после каждого вызова exec().