2010-06-23 2 views
1
<html><body><script> 
var matches = /(\w+)(\s*(\w+))?/.exec("aaa"); 
alert(matches.length); 
alert(typeof(matches[3])); 
</script></body><html> 

저는 정규 표현식에 처음으로 익숙하기 때문에 매우 쉬운 질문 일 수 있습니다.자바에서 정규 표현식의 물음표 (별난 행동)

/(\w+)(\s*(\w+))?/ 위의 정규 표현식은 "aaa", "123", "my_var"또는 "aaa bbb", "123 456", "my_var my_value"와 일치합니다. "AAA BBB"와 같은 표현을위한

는 나를 놀라게 ["aaa", "aaa", ???, ???]

가장 먼저하는 일이 내가 기대 한 그 matches.length = 4입니다 = = ["aaa bbb", "aaa", " bbb", "bbb"] 일치하지만 "AAA"와 같은 표현과 일치 그것은 2가되어야하지만, 나는 그것이 무엇이어야 하는지를 설명하는 어떠한 문서도 보지 못한다. 어떻게 작동합니까?

그리고 나를 놀라게 두 번째 것은 2 "추가"나는 내가 이것을 테스트 한 두 브라우저에서 다른 작업하고있어 일치하는지입니다 :

  • 파이어 폭스 3.6.3에서 일치 [2]와 matches [3]는 정의되지 않습니다.

  • Internet Explorer 6에서 [2]와 (와) 일치하는 항목은 빈 문자열입니다. 나는 ("AAA"와 같은) "짧은"또는 "긴"(같은 "AAA BBB") 식을 가지고있는 경우에 기본적으로

, 어떻게 확인해야합니까?

답변

3

표준 (ECMAScript 5)은 매우 명확합니다. 길이는 4이어야하며 IE는 잘못되었습니다 (충격적입니다.).

§15.10.2.1에서 "NcapturingParens은 왼쪽 캡처 괄호의 총 수입니다." 넌

3이 "A 상태에서는 순서쌍 (endIndex에 캡처) endIndex에 정수이고 NcapturingParens 값의 내부 배열 캡처 곳이다. .. .] 의 n 번째 요소 인은 캡처 괄호의 n 번째 세트에서 얻은 값을 나타내는 문자열이거나 캡처 링 괄호의 n 번째 세트에 아직 도달하지 않은 경우 이 정의되지 않은 인 경우 undefined입니다."간부에 대해 설명

§15.10.6.2는 말한다 :..

9 디 R이 호출의 결과하자 [[경기] [...]

12. 는 NR의 길이하자가 배열을 캡처한다. (이 15.10.2.1의 NCapturingParens 같은 값이다.)

13. A를 new Array() [...]와 같은 식으로 생성 된 새로운 배열이라고합시다.

17. "[DefineOwnProperty]] 내부 메서드 A을"length ", 속성 설명자 {[[Value]] : I + 1} 및 true로 호출하십시오. [...]

20. 각 정수 들어 난 0및 I는 N

하로> 같은 있다. captureI은 요소는 r 배열입니다.

b. 인수 ToString와 의 [DefineOwnProperty] 내부 방법 (I)를 호출, 속성 디스크립터 {[값] : captureI, [기록 가능] 참 [Enumerable에서가] : 참 [[Configurable]] : true} 및 true.

21. A을 반환하십시오.

길이가 반드시 4 (3 + 1)이어야하고 도달하지 못한 캡처 (예 : (\s*(\w+)))는 정의되지 않은 상태로 유지됩니다. 다행히도 은 정의되지 않았습니다."" (빈 문자열)은 모두 위증입니다. 이것은 부울로 처리 될 때 false라는 것을 의미합니다. 그래서이 두 정규 표현식에 그것을 시도 if(matches[2])

+0

정확히 내가보고 싶었던 부분입니다. :) – GameZelda

3

matches 배열에는 일치하는 문자열과 포용 된 패턴이라는 두 가지 종류가 있습니다. 따라서이 경우 네 개의 요소가 있습니다. 전체 일치 문자열 "aaa" 첫 번째 하위 결과 "aaa"이 다시 입력되고 (\s*(\w+))(\w+)은 모두 비어 있습니다.

파이어 폭스와 IE의 차이는 간단합니다.

일치하는 결과를 확인하는 방법에 대한 대답은 간단합니다. matches[1]matches[3]의 값을 확인하여 정의되지 않았거나 비어 있는지 확인하십시오. 파싱 ​​할 문자열이 모두 \w+\s*\w+의 패턴 인 경우 해당 문자는 String.split()입니다. 결과 배열은 문자열이 짧으면 짧을 것이고 문자열이 "aaaa bbbb"이면 길어질 것입니다. 그래도 "aaa " 같은 경우에는주의해야합니다.

+0

첫 번째 질문에 대해서는 4 대신 2 개의 일치를 기대했습니다. 그러나 모든 괄호 유형에 대해 일치를 반환하는 것은 의미가 있습니다. 두 번째 질문은 진정한 의심입니다. 나는 두 가지 다른 행동을 보았으므로 나는 그것이 무엇이되어야하는지 알지 못한다. if (matches [2])는 두 가지 모두에서 작동하는 것처럼 보이지만 이에 대한 문서를보고 싶습니다. 실제 정규 표현식이 실제로 길고 복잡하기 때문에 String.split()을 사용할 수 없습니다. – GameZelda

+0

@GameZelda "", 0 및 정의되지 않은 JavaScript의 모든 false 값입니다. 이 동작을 두려워하는 경우 두 조건을 모두 확인하십시오. 예 : 'if (일치 유형 [2] === "정의되지 않음"|| matches [2] === "") ' – nil

2

을 수행하여 IE의 버그를 해결 할 수 있습니다

첫 번째 경우에
var m1 = /(\w+)(\s*)/.exec("aaa"); // ["aaa", "aaa", ""] 
var m2 = /(\w+)(\s+)?/.exec("aaa"); // ["aaa", "aaa", undef] 

, 그룹 2는 모든 문자를 소비하지 않지만, *는 제로를 의미 길이가 맞다. 해당 그룹은 과 일치하지 않습니다. - i.e., 빈 문자열. 두 번째 경우에는 (\s+)이 실패하지만 그룹 자체가 선택 사항이므로 전체 일치가 성공합니다. undef 결과는 그룹이에 참여하지 않았 음을 나타냅니다.

이것이 작동하는 방식입니다. 빈 문자열은 그룹이 경기에 참가했지만 어떤 문자도 소비하지 않았 음을 의미합니다. undef은 경기에 참여하지 않았 음을 의미합니다.비 참여 그룹에 대해 빈 문자열을 반환하면 Internet Explorer는 아무 것도 검색하지 않는 그룹과 일치하지 않는 그룹 간의 구분을 지 웁니다.

상황은 훨씬 더 심각하지만 IE는 유일한 나쁜 사람이 아닙니다. 자세한 내용은 this blog post을 참조하십시오.

모든 브라우저가 동의하는 한 가지가 있습니다. match 배열의 요소 수는 일치 여부에 관계없이 정규식의 캡처 그룹 수에 의해 제어됩니다.

관련 문제