자바 스크립트에서 첫 번째 첫 번째 매개 변수의 문자열 대신 정규 표현식을 사용하면서 두 번째 매개 변수를 허용하는 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를 사용하는 것과 결과가 동일한 지 확인하기 위해 다음과 같이 테스트하고 있습니다.
// xes
test ( ‘xxx’); 중 a를 찾으십시오 .
테스트 ( ‘axx’);
테스트 ( ‘xax’);
테스트 ( ‘xxa’);
테스트 ( ‘axa’);
테스트 ( ‘xaa’);
테스트 ( ‘aax’);
테스트 ( ‘aaa’);
답변
이미 언급 한 몇 가지 접근법 (indexOf는 분명히 간단합니다)을 결합하여 트릭을 수행하는 함수라고 생각합니다.
String.prototype.regexIndexOf = function(regex, startpos) {
var indexOf = this.substring(startpos || 0).search(regex);
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
}
String.prototype.regexLastIndexOf = function(regex, startpos) {
regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
if(typeof (startpos) == "undefined") {
startpos = this.length;
} else if(startpos < 0) {
startpos = 0;
}
var stringToWorkWith = this.substring(0, startpos + 1);
var lastIndexOf = -1;
var nextStop = 0;
while((result = regex.exec(stringToWorkWith)) != null) {
lastIndexOf = result.index;
regex.lastIndex = ++nextStop;
}
return lastIndexOf;
}
분명히 내장 String 객체를 수정하면 대부분의 사람들에게 붉은 깃발을 보낼 수 있지만, 그렇게 큰 일이 아닐 수도 있습니다. 간단히 알아 두십시오.
업데이트 : 지금 regexLastIndexOf()
모방 된 것처럼 편집 lastIndexOf()
되었습니다. 그래도 실패하면 어떤 상황에서 알려주십시오.
업데이트 :이 페이지의 주석에서 찾은 모든 테스트와 내 테스트를 통과합니다. 물론 이것이 방탄을 의미하지는 않습니다. 모든 의견을 부탁드립니다.
답변
String
생성자의 인스턴스 에는 RegExp를 허용하고 첫 번째 일치하는 인덱스를 반환 하는 .search()
메서드 가 있습니다.
특정 위치에서 검색을 시작하려면 (의 두 번째 매개 변수에 해당 .indexOf()
) slice
첫 번째 i
문자를 해제 할 수 있습니다 .
str.slice(i).search(/re/)
그러나 이것은 짧은 문자열 (첫 번째 부분이 슬라이스 된 후)에 i
색인 을 가져 오므로 잘린 부분 ( ) 의 길이를 반환되지 않은 인덱스에 반환하려고합니다 -1
. 이렇게하면 원래 문자열의 색인이 제공됩니다.
function regexIndexOf(text, re, i) {
var indexInSuffix = text.slice(i).search(re);
return indexInSuffix < 0 ? indexInSuffix : indexInSuffix + i;
}
답변
짧은 버전이 있습니다. 그것은 나를 위해 잘 작동합니다!
var match = str.match(/[abc]/gi);
var firstIndex = str.indexOf(match[0]);
var lastIndex = str.lastIndexOf(match[match.length-1]);
그리고 프로토 타입 버전을 원한다면 :
String.prototype.indexOfRegex = function(regex){
var match = this.match(regex);
return match ? this.indexOf(match[0]) : -1;
}
String.prototype.lastIndexOfRegex = function(regex){
var match = this.match(regex);
return match ? this.lastIndexOf(match[match.length-1]) : -1;
}
편집 : fromIndex에 대한 지원을 추가하려는 경우
String.prototype.indexOfRegex = function(regex, fromIndex){
var str = fromIndex ? this.substring(fromIndex) : this;
var match = str.match(regex);
return match ? str.indexOf(match[0]) + fromIndex : -1;
}
String.prototype.lastIndexOfRegex = function(regex, fromIndex){
var str = fromIndex ? this.substring(0, fromIndex) : this;
var match = str.match(regex);
return match ? str.lastIndexOf(match[match.length-1]) : -1;
}
다음과 같이 간단하게 사용하십시오.
var firstIndex = str.indexOfRegex(/[abc]/gi);
var lastIndex = str.lastIndexOfRegex(/[abc]/gi);
답변
답변
BaileyP의 답변을 기반으로합니다. 가장 큰 차이점은 -1
패턴을 일치시킬 수없는 경우 이러한 메소드가 리턴한다는 것입니다.
편집 : Jason Bunting의 답변 덕분에 아이디어가 생겼습니다. 왜 .lastIndex
정규식 의 속성을 수정하지 않습니까? 비록 이것이 글로벌 플래그 ( /g
) 가있는 패턴에서만 작동합니다 .
편집 : 테스트 사례를 통과하도록 업데이트되었습니다.
String.prototype.regexIndexOf = function(re, startPos) {
startPos = startPos || 0;
if (!re.global) {
var flags = "g" + (re.multiline?"m":"") + (re.ignoreCase?"i":"");
re = new RegExp(re.source, flags);
}
re.lastIndex = startPos;
var match = re.exec(this);
if (match) return match.index;
else return -1;
}
String.prototype.regexLastIndexOf = function(re, startPos) {
startPos = startPos === undefined ? this.length : startPos;
if (!re.global) {
var flags = "g" + (re.multiline?"m":"") + (re.ignoreCase?"i":"");
re = new RegExp(re.source, flags);
}
var lastSuccess = -1;
for (var pos = 0; pos <= startPos; pos++) {
re.lastIndex = pos;
var match = re.exec(this);
if (!match) break;
pos = match.index;
if (pos <= startPos) lastSuccess = pos;
}
return lastSuccess;
}
답변
substr을 사용할 수 있습니다.
str.substr(i).match(/[abc]/);
답변
RexExp
인스턴스에는 이미 lastIndex 속성이 있습니다 (글로벌 인 경우). 내가하는 일은 정규 표현식을 복사하여 목적에 맞게 약간 수정 exec
하고 문자열 에서 확인 하고을 보는 것 lastIndex
입니다. 이것은 문자열을 반복하는 것보다 필연적으로 빠릅니다. (이것을 문자열 프로토 타입에 넣는 방법에 대한 충분한 예가 있습니까?)
function reIndexOf(reIn, str, startIndex) {
var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : ''));
re.lastIndex = startIndex || 0;
var res = re.exec(str);
if(!res) return -1;
return re.lastIndex - res[0].length;
};
function reLastIndexOf(reIn, str, startIndex) {
var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')';
var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : ''));
re.lastIndex = startIndex || 0;
var res = re.exec(str);
if(!res) return -1;
return re.lastIndex - res[0].length;
};
reIndexOf(/[abc]/, "tommy can eat"); // Returns 6
reIndexOf(/[abc]/, "tommy can eat", 8); // Returns 11
reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11
RegExp 객체에 함수를 프로토 타입 할 수도 있습니다.
RegExp.prototype.indexOf = function(str, startIndex) {
var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));
re.lastIndex = startIndex || 0;
var res = re.exec(str);
if(!res) return -1;
return re.lastIndex - res[0].length;
};
RegExp.prototype.lastIndexOf = function(str, startIndex) {
var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')';
var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));
re.lastIndex = startIndex || 0;
var res = re.exec(str);
if(!res) return -1;
return re.lastIndex - res[0].length;
};
/[abc]/.indexOf("tommy can eat"); // Returns 6
/[abc]/.indexOf("tommy can eat", 8); // Returns 11
/[abc]/.lastIndexOf("tommy can eat"); // Returns 11
수정 방법에 대한 간단한 설명 RegExp
: indexOf
전역 플래그가 설정되어 있는지 확인해야합니다. 들어 lastIndexOf
나는하지 않는 한 마지막 발생을 찾을 부정적인 모양 미리를 사용하고의 RegExp
이미 문자열의 끝에 일치했다.