programing

글로벌 플래그가 있는 RegExp에서 잘못된 결과가 나타나는 이유는 무엇입니까?

copysource 2022. 9. 25. 14:40
반응형

글로벌 플래그가 있는 RegExp에서 잘못된 결과가 나타나는 이유는 무엇입니까?

글로벌 플래그와 대소문자를 구분하지 않는 플래그를 사용할 때 이 정규 표현에 문제가 있는 것은 무엇입니까?쿼리는 사용자가 생성한 입력입니다.결과는 [참, 참]이 될 것이다.

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"));

A RegExp에 이의를 제기하다gflag는 매치가 발생한 위치를 추적하기 때문에 이후의 일치에서는 0이 아닌 마지막으로 사용한 인덱스에서 시작합니다.다음 항목을 참조하십시오.

var query = 'Foo B';
var re = new RegExp(query, 'gi');
console.log(re.lastIndex);

console.log(re.test('Foo Bar'));
console.log(re.lastIndex);

console.log(re.test('Foo Bar'));
console.log(re.lastIndex);

수동으로 리셋하지 않는 경우lastIndex모든 테스트 후 0으로 하려면g플래그를 설정합니다.

사양에 의해 지시되는 알고리즘은 다음과 같습니다(섹션 15.10.6.2).

RegExp.protype.exec(문자열)

정규 표현과 문자열의 정규 표현을 대조하여 일치 결과를 포함하는 배열 개체를 반환합니다.문자열이 일치하지 않으면 null을 반환합니다.문자열 ToString(string)은 다음과 같이 정규 표현 패턴의 발생을 검색합니다.

  1. R을 이 RexExp 객체로 합니다.
  2. S를 ToString(string)의 값으로 합니다.
  3. 길이를 S의 길이라고 하자.
  4. 오래가도록 놔두자Index는 R의 lastIndex 속성 값입니다.
  5. i를 ToInteger(lastIndex)의 값으로 합니다.
  6. 글로벌 속성이 false이면 i = 0으로 합니다.
  7. i < 0 또는 i > lastIndex 속성을 0으로 설정하고 null을 반환합니다.
  8. [Match]를 호출하여 인수 S와 i를 지정합니다.[Match]가 장애를 반환한 경우 스텝9로 넘어갑니다.그렇지 않은 경우 r을 State 결과로 하고 스텝10으로 넘어갑니다
  9. i = i+1로 하자.
  10. 스텝 7로 넘어갑니다.
  11. e를 r의 endIndex 값으로 합니다.
  12. 글로벌 속성이 true인 경우 RlastIndex 속성을 e로 설정합니다.
  13. n은 r의 캡처 배열 길이입니다.(이것은 15.10.2.1의 NCapturingParens와 같은 값입니다).
  14. 다음 속성을 가진 새 어레이를 반환합니다.
  • 인덱스 속성은 완전한 문자열 S 내에서 일치하는 서브스트링의 위치로 설정됩니다.
  • 입력 속성이 S로 설정됩니다.
  • length 속성은 n + 1로 설정됩니다.
  • 0 속성은 일치하는 하위 문자열로 설정됩니다(즉, 오프셋 i 포함과 오프셋 e 제외 사이의 S 부분).
  • i > 0 및 i n n의 각 정수 i에 대해 ToString(i)이라는 속성을 r의 캡처 배열의 ith 요소로 설정합니다.

싱글을 사용하고 있습니다.RegExp오브젝트 및 여러 번 실행합니다.연속적으로 실행할 때마다 마지막 일치 색인부터 계속됩니다.

각 실행 전에 처음부터 regex를 "리셋"해야 합니다.

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 는 정규 표현식의 속성을 업데이트하여 각 테스트가 마지막으로 중지된 위치에서 시작되도록 합니다.속성을 업데이트하지 않기 때문에 다음을 사용하는 것이 좋습니다.

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true

참고: 부울로 변환한 다음 결과를 반영하도록 부울을 반전합니다.

또는 속성을 리셋할 수도 있습니다.

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');

g 플래그를 사용하여 regex가 마지막으로 일치한 내용을 계속 추적하므로 re.lastIndex = 0을 설정해야 합니다. 따라서 re.lastIndex = 0을 수행해야 합니다.

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
re.lastIndex=0;
result.push(re.test('Foo Bar'));

console.log(result)

/g 플래그를 사용하면 히트 후 검색을 계속하도록 지시합니다.

일치가 성공하면 exec() 메서드는 배열을 반환하고 정규 표현 객체의 속성을 업데이트합니다.

첫 번째 검색 전:

myRegex.lastIndex
//is 0

첫 번째 검색 후

myRegex.lastIndex
//is 8

g를 삭제하면 exec()에 대한 콜이 끝날 때마다 검색이 종료됩니다.

저는 다음과 같은 기능을 가지고 있습니다.

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된다.이치

언급URL : https://stackoverflow.com/questions/1520800/why-does-a-regexp-with-global-flag-give-wrong-results

반응형