В javascript есть ли эквивалент String.indexOf (), который принимает регулярное выражение вместо строки для первого первого параметра, но при этом разрешает второй параметр?
Мне нужно сделать что-то вроде
str.indexOf(/[abc]/ , i);
и
str.lastIndexOf(/[abc]/ , i);
Хотя String.search () принимает в качестве параметра регулярное выражение, он не позволяет мне указать второй аргумент!
Изменить:
это оказалось сложнее, чем я думал, поэтому я написал небольшую тестовую функцию для проверки всех предоставленных решений ... предполагается, что regexIndexOf и regexLastIndexOf были добавлены в объект String.
function test (str) {
var i = str.length +2;
while (i--) {
if (str.indexOf('a',i) != str.regexIndexOf(/a/,i))
alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) )
alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
}
}
и я проверяю, как следует, чтобы убедиться, что по крайней мере для одного символа регулярное выражение, результат такой же, как если бы мы использовали indexOf
// ищем a среди xes
test ('xxx');
тест ( 'ахх');
тест ( 'хах');
тест ( 'XXA');
тест ( 'ах');
тест ( 'Хаа');
тест ( 'а');
тест ( 'ааа');
источник
|
внутри[ ]
соответствует буквальному символу|
. Вы, наверное, имели в виду[abc]
.Ответы:
Комбинируя некоторые из уже упомянутых подходов (indexOf, очевидно, довольно прост), я думаю, что эти функции помогут вам:
Очевидно, что изменение встроенного объекта String вызовет красные флаги для большинства людей, но это может быть один раз, когда это не так уж важно; просто знайте об этом.
ОБНОВЛЕНИЕ: отредактировано
regexLastIndexOf()
так, что это, кажется,lastIndexOf()
теперь подражает . Пожалуйста, дайте мне знать, если это все еще не удается и при каких обстоятельствах.ОБНОВЛЕНИЕ: Проходит все тесты, найденные в комментариях на этой странице, и мои собственные. Конечно, это не значит, что это пуленепробиваемый. Любые отзывы приветствуются.
источник
regexLastIndexOf
только индекс последнего непересекающегося матча.regex.lastIndex = result.index + 1;
вместоregex.lastIndex = ++nextStop;
. Мы надеемся, что следующий матч будет проходить намного быстрее, без потери результата.Экземпляры
String
конструктора имеют.search()
метод, который принимает RegExp и возвращает индекс первого совпадения.Чтобы начать поиск с определенной позиции (имитируя второй параметр
.indexOf()
), вы можетеslice
отключить первыеi
символы:Но это приведет к получению индекса в более короткой строке (после обрезки первой части), поэтому вы захотите добавить длину отрубленной части (
i
) к возвращаемому индексу, если это не так-1
. Это даст вам индекс в исходной строке:источник
function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
У меня есть короткая версия для вас. Это хорошо работает для меня!
И если вы хотите прототип версии:
РЕДАКТИРОВАТЬ : если вы хотите добавить поддержку fromIndex
Чтобы использовать это, так просто, как это:
источник
startIndex
параметр как обычноindeoxOf
иlastIndexOf
сделать.startIndex
(илиfromIndex
). Надеюсь, поможет!lastIndexOfRegex
Также следует добавить обратно значениеfromIndex
к результату."aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));
результат будет 1, когда он должен быть 7, потому что indexOf будет искать в первый раз «romeo», независимо от того, находится он в начале слова или нет.Использование:
Смотрите документацию здесь.
источник
0
, и был опубликован ... семь лет спустя.На основании ответа BaileyP. Основное отличие состоит в том, что эти методы возвращаются,
-1
если шаблон не может быть сопоставлен.Изменить: Благодаря ответу Джейсона Бантинга у меня появилась идея. Почему бы не изменить
.lastIndex
свойство регулярного выражения? Хотя это будет работать только для шаблонов с глобальным флагом (/g
).Изменить: Обновлено, чтобы пройти тест-кейсы.
источник
Вы можете использовать substr.
источник
RexExp
экземпляры уже имеют свойство lastIndex (если они глобальные), поэтому я копирую регулярное выражение, слегка его модифицируя в соответствии с нашими целями,exec
определяя его в строке и просматриваяlastIndex
. Это неизбежно будет быстрее, чем зацикливание строки. (У вас достаточно примеров того, как поместить это в прототип строки, верно?)Вы также можете создать прототип функции для объекта RegExp:
Краткое объяснение того, как я изменяю
RegExp
:indexOf
я просто должен убедиться, что установлен глобальный флаг. Из-заlastIndexOf
того, что я использую отрицательный прогноз, чтобы найти последнее вхождение, если оноRegExp
уже не совпадает в конце строки.источник
Это не изначально, но вы, конечно, можете добавить эту функциональность
Я не полностью протестировал эти методы, но они, кажется, работают до сих пор.
источник
После того, как все предложенные решения так или иначе не прошли мои тесты, (отредактируйте: некоторые были обновлены, чтобы пройти тесты после того, как я написал это), я нашел реализацию mozilla для Array.indexOf и Array.lastIndexOf
Я использовал их для реализации моей версии String.prototype.regexIndexOf и String.prototype.regexLastIndexOf следующим образом:
Кажется, они проходят тестовые функции, которые я предоставил в вопросе.
Очевидно, они работают, только если регулярное выражение соответствует одному символу, но этого достаточно для моей цели, так как я буду использовать его для таких вещей, как ([abc], \ s, \ W, \ D)
Я буду следить за вопросом в случае, если кто-то предоставит лучшую / более быструю / более чистую / более общую реализацию, которая работает с любым регулярным выражением.
источник
Мне также нужна была
regexIndexOf
функция для массива, поэтому я сам ее запрограммировал. Однако я сомневаюсь, что это оптимизировано, но я думаю, что это должно работать правильно.источник
В некоторых простых случаях вы можете упростить поиск в обратном направлении, используя разделение.
Это имеет несколько серьезных проблем:
Но с другой стороны, это намного меньше кода. Для регулярных выражений постоянной длины, которые не могут перекрываться (например,
/\s\w/
для нахождения границ слов), этого достаточно.источник
Для данных с разреженными совпадениями использование string.search является самым быстрым в браузерах. Каждую итерацию повторно разрезает строку на:
Для плотных данных я сделал это. Он сложен по сравнению с методом execute, но для плотных данных он в 2-10 раз быстрее, чем любой другой метод, который я пробовал, и примерно в 100 раз быстрее, чем принятое решение. Основными моментами являются:
Выполняется новое регулярное выражение и возвращаются результаты либо этого exec, либо первого exec;
jsPerf методов
Я не понимаю цели тестов сверху. Ситуации, требующие регулярного выражения, невозможно сравнить с вызовом indexOf, который, на мой взгляд, и является главной целью создания метода. Чтобы пройти тест, имеет больше смысла использовать «xxx + (?! x)», чем настраивать способ итерации регулярного выражения.
источник
Последний индекс Джейсона Бантинга не работает. Мой не оптимален, но работает.
источник
Все еще нет собственных методов, которые выполняют запрошенную задачу.
Вот код, который я использую. Он имитирует поведение методов String.prototype.indexOf и String.prototype.lastIndexOf, но они также принимают RegExp в качестве аргумента поиска в дополнение к строке, представляющей значение для поиска.
Да, это довольно длинный ответ, поскольку он пытается следовать действующим стандартам настолько близко, насколько это возможно, и, конечно, содержит разумное количество комментариев JSDOC . Тем не менее, после минимизации код составляет всего 2,27 Кбайт, а один раз сжатый для передачи - только 1023 байта.
2 метода, которые это добавляет
String.prototype
(используя Object.defineProperty, где доступно):searchOf
searchLastOf
Он проходит все тесты, которые опубликовал OP, и, кроме того, я довольно тщательно протестировал подпрограммы в своем ежедневном использовании и пытался убедиться, что они работают в разных средах, но отзывы / проблемы всегда приветствуются.
источник
Если вы ищете очень простой поиск lastIndex с RegExp и вам все равно, будет ли он повторять lastIndexOf до последней детали, это может привлечь ваше внимание.
Я просто переворачиваю строку и вычитаю индекс первого вхождения из длины - 1. Это проходит мой тест, но я думаю, что могут возникнуть проблемы с производительностью с длинными строками.
источник
Я использовал
String.prototype.match(regex)
метод, который возвращает строковый массив всех найденных совпадений заданногоregex
в строке (подробнее см. Здесь ):источник
Используйте стандартные регулярные выражения:
источник
Ну, так как вы просто ищете, чтобы соответствовать позиции персонажа , регулярное выражение возможно излишне.
Я предполагаю, что все, что вы хотите, вместо того, чтобы «найти первым из этих символов», просто найти первым из этих символов.
Это, конечно, простой ответ, но он выполняет то, что намеревается сделать ваш вопрос, хотя и без части регулярного выражения (потому что вы не выяснили, почему конкретно это должно быть регулярное выражение)
источник