[javascript] RegExp의 exec () 함수와 String의 match () 함수의 차이점은 무엇입니까?

이것을 실행하면 :

/([^\/]+)+/g.exec('/a/b/c/d');

나는 이것을 얻는다 :

["a", "a"]

그러나 이것을 실행하면 :

'/a/b/c/d'.match(/([^\/]+)+/g);

그런 다음 예상되는 결과를 얻습니다.

["a", "b", "c", "d"]

차이점이 뭐야?



답변

exec전역 정규식을 사용하는 것은 여전히 ​​일치하는 모든 하위 표현식을 검색하므로 루프에서 사용됩니다. 그래서:

var re = /[^\/]+/g;
var match;

while (match = re.exec('/a/b/c/d')) {
    // match is now the next match, in array form.
}

// No more matches.

String.match 이 작업을 수행하고 캡처 된 그룹을 버립니다.


답변

한 장의 사진이 더 좋습니다.

re_once = /([a-z])([A-Z])/
re_glob = /([a-z])([A-Z])/g

st = "aAbBcC"

console.log("match once="+ st.match(re_once)+ "  match glob="+ st.match(re_glob))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))

차이점이 보이십니까?

참고 : 강조 표시하려면 일치 된 패턴 (예 : aA) 후에 캡처 된 그룹 (예 : a, A)이 반환되며 일치하는 패턴이 아닙니다.


답변

/regex/.exec()찾은 첫 번째 일치 항목 만 "string".match()반환 g하고 정규 표현식 에서 플래그 를 사용하면 모두 반환합니다 .

여기를보십시오 : exec , match .


답변

정규식이 전역이고 캡처하는 경우 exec를 사용해야합니다. Match는 모든 캡처를 반환하지 않습니다.

일치는 일치 (캡처하지 않음) 할 때 효과적입니다. 한 번 실행하면 모든 일치 항목이 배열됩니다. (정규식이 전역이 아닌 경우 일치는 일치를 표시하고 캡처가 이어짐)

Exec은 캡처 할 때 사용하는 것이며 실행될 때마다 일치를 제공하고 캡처가 이어집니다. (일치는 정규식이 전역이 아닌 경우에만 전체 일치 후 캡처를 제공하는 방식으로 작동합니다).

Exec의 또 다른 용도는 일치 항목의 인덱스 또는 위치를 가져 오는 것입니다. 정규식에 대한 변수가 있으면 .lastIndex를 사용하여 일치하는 위치를 가져올 수 있습니다. regex 객체에는 .lastIndex가 있고 regex 객체는 .exec를 수행하는 작업입니다. 점 일치는 문자열에서 수행되며 정규식 개체 dot lastIndex를 수행 할 수 없습니다.

문자열에는 정규식이 전달되는 일치 함수가 있습니다. 정규식에는 exec 함수가 있으며 문자열이 전달됩니다.

exec 당신은 여러 번 실행합니다. 한 번 뛰는 경기

캡처하지 않을 때 match를 사용하는 것이 좋으며 캡처 할 때 캡처를 얻는 데 유용하기 때문에 더 강력한 exec를 사용할 수 있지만 캡처 할 때 match를 사용했다면 정규식이 전역이 아닌 경우 캡처를 표시하는 것을 확인하십시오. 정규식이 전역일 때 캡처를 표시하지 않습니다.

> "azb".match(/a(z)b/);
[ "azb", "z" ]

> "azb".match(/a(z)b/g);
[ "azb" ]
>

또 다른 것은 exec를 사용하는 경우 정규식에서 호출된다는 점에 유의하고 정규식에 대한 변수를 사용하면 더 많은 권한을 갖게됩니다.

정규식에 변수를 사용하지 않으면 일치 항목을 얻지 못하므로 exec를 사용할 때 정규식에 대한 변수를 사용하십시오.

> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
>
> /[a-c]/g.exec("abc")
[ "a" ]
> /[a-c]/g.exec("abc")
[ "a" ]
>

> var r=/[a-c]/g
> r.exec("abc")
[ "a" ]
> r.exec("abc")
[ "b" ]
> r.exec("abc")
[ "c" ]
> r.exec("abc")
null
>

그리고 exec를 사용하면 일치의 “인덱스”를 얻을 수 있습니다.

> var r=/T/g
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
2
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
6
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
9
> r.exec("qTqqqTqqTq");
null
> r.lastIndex
0
>

따라서 인덱스 또는 캡처를 원하면 exec를 사용하십시오 ( “인덱스”와 함께 제공되는 “인덱스”는 실제로 n 번째 발생이며 1에서 계산됩니다. 따라서 적절한 값을 유도 할 수 있습니다. 1을 빼서 색인을 생성합니다. 그리고 보시다시피 0-lastIndex 0-찾을 수 없음)을 제공합니다.

일치를 늘리려면 캡처 할 때 사용할 수 있지만 정규식이 전역일 때는 사용할 수 없으며이를 위해 수행 할 때 배열의 내용이 모두 일치하는 것은 아니지만 전체 캡처 후 일치합니다.


답변

.match () 함수는 str.match(regexp)다음 작업을 수행합니다 :

  • 이 경우 입니다 일치가 반환합니다 :
    • g플래그 정규 표현식에서 사용되는 경우 : 모든 하위 문자열을 반환합니다 (캡처 그룹 무시).
    • 경우 g플래그가되어 있지 정규 표현식에 사용 : 그것은 같은를 반환합니다regexp.exec(str)
  • 일치하는 항목 이 없으면 다음을 반환합니다.
    • null

플래그를 사용하는 .match ()의g:

var str = "qqqABApppabacccaba";
var e1, e2, e3, e4, e5;
e1 = str.match(/nop/g); //null
e2 = str.match(/no(p)/g); //null
e3 = str.match(/aba/g); //["aba", "aba"]
e4 = str.match(/aba/gi); //["ABA", "aba", "aba"]
e5 = str.match(/(ab)a/g); //["aba", "aba"] ignoring capture groups as it is using the g flag

그리고 플래그가 없는 .match ()g.exec ()와 같습니다.

e1=JSON.stringify(str.match(/nop/))===JSON.stringify(/nop/.exec(str)); //true
//e2 ... e4 //true
e5=JSON.stringify(str.match(/(ab)a/))===JSON.stringify(/(ab)a/.exec(str)); //true

.exec () 함수는 regexp.exec(str)다음 작업을 수행합니다 :

  • 이 경우 입니다 일치가 반환합니다 :
    • g플래그 정규 표현식에서 사용되는 경우 : 다음 일치 항목을 ( 호출 될 때마다) 반환 합니다. 중요 : regexp 객체가 변수에 저장되지 않은 경우 다음 일치 항목으로 진행되지 않습니다 (동일한 객체 여야 함).[N_MatchedStr, N_Captured1, N_Captured2, ...]N
    • g플래그가 정규 표현식에서 사용 되지 않는 경우 : 플래그가 g있고 처음으로 한 번만 호출 된 것처럼 동일한 결과를 반환합니다 .
  • 일치하는 항목 이 없으면 다음을 반환합니다.
    • null

.exec ()의 예 (저장된 regexp + g플래그 사용 = 각 호출에 따라 변경됨) :

var str = "qqqABApppabacccaba";
var myexec, rgxp = /(ab)a/gi;

myexec = rgxp.exec(str);
console.log(myexec); //["ABA", "AB"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //null

//But in this case you should use a loop:
var mtch, myRe = /(ab)a/gi;
while(mtch = myRe.exec(str)){ //infinite looping with direct regexps: /(ab)a/gi.exec()
    console.log("elm: "+mtch[0]+" all: "+mtch+" indx: "+myRe.lastIndex);
    //1st iteration = elm: "ABA" all: ["ABA", "AB"] indx: 6
    //2nd iteration = elm: "aba" all: ["aba", "ab"] indx: 12
    //3rd iteration = elm: "aba" all: ["aba", "ab"] indx: 18
}

.exec () 가 호출 할 때 마다 변경 되지 않는 경우의 예 :

var str = "qqqABApppabacccaba", myexec, myexec2;

//doesn't go into the next one because no g flag
var rgxp = /(a)(ba)/;
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
//... ["aba", "a", "ba"]

//doesn't go into the next one because direct regexp
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
//... ["ABA", "AB"]


답변

때때로 regex.exec ()는 string.match () 보다 훨씬 더 많은 시간 이 걸립니다 .

string.match ()와 regex.exec ()의 결과가 같으면 (예 : \ g 플래그를 사용하지 않을 때) regex.exec ()는 x2에서 x30 사이의 어딘가를 취한 다음 string을 취합니다. 시합():

따라서 이러한 경우 “new RegExp (). exec ()”접근 방식을 사용하는 것은 전역 정규식이 필요할 때만 사용해야합니다 (예 : 두 번 이상 실행).


답변