Я не уверен, в чем проблема, но запуск exec() внутри цикла for в Javascript (Nodejs, консоль Chrome, консоль Firefox) дает неправильные результаты. Насколько мне известно, exec() — это синхронный метод, вызываемый внутри синхронного цикла, который должен давать ожидаемый результат.
const FILTER_REGEX = /(\w+)\s+(below|under|lesser than|lower than|above|over|more than|higher than|greater than|equals|equal to|same as|>|<|=)\s+(\d+)/gi;
const searchQuery = "Package Quantity > 50000 Date yearly ListPrice above 100";
const filterMatches = searchQuery.match(FILTER_REGEX) || [];
for(const filterMatch of filterMatches) {
const filterMatchGroups = FILTER_REGEX.exec(filterMatch);
console.info(`filterMatch: ${filterMatch}, filterMatchGroups: ${filterMatchGroups}`);
}
В настоящее время я получаю следующее в качестве вывода: иногда filterMatchGroups для первой строки становится нулевым и дает filterMatchGroups для второй.
filterMatch: Quantity > 50000, filterMatchGroups: Quantity > 50000,Quantity,>,50000
filterMatch: ListPrice above 100, filterMatchGroups: null
Почти так и есть, но этот вопрос пока открыт. Проблема в том, что ваш FILTER_REGEX является глобальным и имеет состояние (свойство lastIndex). Если вы каждый раз запускаете новое регулярное выражение, результат будет таким, как ожидалось. jsfiddle.net/fy0p9jbk
@CertainPerformance Разве глобальный идентификатор не означает, что он находит все совпадения, а не останавливается на первом, верно? Поправьте меня, если я ошибаюсь.
Не тогда, когда вы используете .exec, который вернет совпадение следующий (пока оно не дойдет до конца и не сможет найти больше совпадений, а затем начнется сначала)
@Andreas Спасибо, я не знал, что он также использует последний индекс для следующей проверки, поэтому я надеюсь, что сброс lastIndex регулярного выражения должен сделать все хорошо. Это похоже на действительно хорошую ловушку, которую я бы никогда не понял, если бы не спросил.
Я вообще не заморачиваюсь с exec; это может немного снизить производительность, но я обычно использую replace для поиска всех результатов вместо exec (даже если я не заинтересован в замене чего-либо). Нет надоедливого состояния с replace.
@Amadan Но как получить группы из replace ()?
Вы можете использовать RegExp.lastMatch (MDN говорит, что у него плохая кросс-браузерная совместимость, но я еще не видел, чтобы он терпел неудачу); но стандартным способом будет через параметры обратного вызова.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это должно сделать это.
const FILTER_REGEX = /(\w+)\s+(below|under|lesser than|lower than|above|over|more than|higher than|greater than|equals|equal to|same as|>|<|=)\s+(\d+)/gi;
const searchQuery = "Package Quantity > 50000 Date yearly ListPrice above 100";
const filterMatches = searchQuery.match(FILTER_REGEX) || [];
for(const filterMatch of filterMatches) {
FILTER_REGEX.lastIndex = 0;
const filterMatchGroups = FILTER_REGEX.exec(filterMatch);
console.info(`filterMatch: ${filterMatch}, filterMatchGroups: ${filterMatchGroups}`);
}
Единственным видимым отличием является FILTER_REGEX.lastIndex = 0, мы должны сбросить свойство lastIndex регулярного выражения, если нам нужно использовать его снова, иначе оно запустит проверку регулярного выражения из ранее сохраненного lastIndex. Спасибо @CertainPerfomance @Andreas за ссылки и объяснение.
Ссылка: Детальное объяснение
@CertainPerfomance Как это дубликат этого вопроса?