[javascript] 정규 표현식을 허용하는 JavaScript의 String.indexOf () 버전이 있습니까?

자바 스크립트에서 첫 번째 첫 번째 매개 변수의 문자열 대신 정규 표현식을 사용하면서 두 번째 매개 변수를 허용하는 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);


답변

사용하다:

str.search(regex)

여기 에서 설명서를 참조 하십시오.


답변

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이미 문자열의 끝에 일치했다.