Se eu executar este:
/([^\/]+)+/g.exec('/a/b/c/d');
Eu entendi isso:
["a", "a"]
Mas se eu executar isso:
'/a/b/c/d'.match(/([^\/]+)+/g);
Então, obtenho o resultado esperado:
["a", "b", "c", "d"]
Qual é a diferença?
fonte
Se eu executar este:
/([^\/]+)+/g.exec('/a/b/c/d');
Eu entendi isso:
["a", "a"]
Mas se eu executar isso:
'/a/b/c/d'.match(/([^\/]+)+/g);
Então, obtenho o resultado esperado:
["a", "b", "c", "d"]
Qual é a diferença?
exec
com uma expressão regular global deve ser usado em um loop, já que ainda recuperará todas as subexpressões correspondentes. Assim:
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
faz isso por você e descarta os grupos capturados.
while(match = /[^\/]+/g.exec('/a/b/c/d')
ou criará um loop infinito !. Como está claramente declarado no MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
new RegExp("pattern")
e /pattern/
significava coisas diferentes.
Uma foto é melhor, sabe ...
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))
Veja a diferença?
Nota: Para realçar, observe que os grupos capturados (por exemplo: a, A) são retornados após o padrão correspondido (por exemplo: aA), não é apenas o padrão correspondido.
Se sua regex for global e você estiver capturando, deverá usar exec. Match não retornará todas as suas capturas.
A correspondência funciona muito bem quando apenas corresponde (não captura). Você o executa uma vez e fornece um array de todas as correspondências. (embora se a regex não for global, a correspondência mostrará a correspondência seguida por capturas)
Exec é o que você usa quando está capturando, e cada vez que é executado dá a correspondência, seguida pelas capturas. (a correspondência se comportará de forma a fornecer a correspondência completa seguida por capturas, apenas quando a regex não for global)
Outro uso com Exec é obter o índice ou posição de uma correspondência. Quando você tem uma variável para sua regex, pode usar .lastIndex e obter a posição da correspondência. Um objeto regex tem .lastIndex, e o objeto regex é o que você faz .exec. A correspondência de pontos é feita em uma string e você não poderá fazer o objeto regex ponto lastIndex
Uma string tem a função match, que é passada a um regex. E uma regex, tem a função exec, e é passada uma string
exec você executa várias vezes. jogo você corre uma vez
É bom usar match quando não estiver capturando e ao capturar você pode usar exec, que é mais poderoso porque é bom para obter capturas, mas se você usou match durante a captura, veja que mostra as capturas quando o regex não é global, mas não mostra capturas quando o regex é global.
> "azb".match(/a(z)b/);
[ "azb", "z" ]
> "azb".match(/a(z)b/g);
[ "azb" ]
>
Outra coisa é que se você usar exec, observe que é chamado na regex, então se você usou uma variável para a regex, você tem mais poder
Você não obtém as correspondências quando não usa a variável para o regex, então use a variável para o regex, ao usar 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
>
E com exec, você pode obter o "índice" da correspondência
> 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
>
Então, se você quiser índices ou captura, use exec (tenha em mente que, como você pode ver, com o "índice", o "índice" que ele dá é na verdade uma enésima ocorrência, está contando a partir de 1. Então você pode derivar o indexe subtraindo 1. E como você pode ver, dá 0 - lastIndex de 0 - para não encontrado).
E se você quiser esticar a correspondência, você pode usá-lo quando estiver capturando, mas não quando a regex for global, e quando você fizer isso para isso, o conteúdo da matriz não é todas as correspondências, mas sim o completo partida seguida pelas capturas.
r.lastIndex
é o fator chave para entender a diferença entre exec
e match
.
If your regex is global, and you are capturing, then you must use exec. Match won't return all your captures.
consegui no console. Basta copiar / colar o "a,b,c,aa,bb,cc".match(/(\w+)/g);
Opera, Firefox.
"a,b,c,aa,bb,cc".match(/(\w+)/g)
O que está acontecendo lá, mostra todas as combinações, e acontece que você capturou todas as combinações, então se fosse para mostrar todas as capturas, seria exatamente o mesmo (cntd)
A função .match ()str.match(regexp)
fará o seguinte:
g
sinalizador for usado no regexp: ele retornará todas as substrings (ignorando grupos de captura)g
sinalizador não for usado no regexp: ele retornará o mesmo queregexp.exec(str)
null
Exemplos de .match () usando o g
sinalizador:
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
E .match () sem o g
sinalizador é equivalente a .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
A função .exec ()regexp.exec(str)
fará o seguinte:
g
sinalizador for usado no regexp: ele retornará (a cada vez que for chamado) : [N_MatchedStr, N_Captured1, N_Captured2, ...]
do próximoN
partida. Importante: não avançará para a próxima partida se o objeto regexp não estiver armazenado em uma variável (precisa ser o mesmo objeto)g
sinalizador não for usado no regexp: ele retornará o mesmo como se tivesse umg
sinalizador e fosse chamado pela primeira vez e apenas uma vez.null
Exemplo de .exec () (regexp armazenado + usando o g
sinalizador = ele muda a cada chamada):
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
}
Exemplos de .exec () quando não muda a cada chamada:
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"]
Às vezes, regex.exec () leva muito mais tempo do que string.match ().
Vale a pena mencionar que se o resultado de string.match () e regex.exec () for o mesmo (ex: quando não estiver usando o sinalizador \ g), regex.exec () levará em algum lugar entre x2 a x30 então string. Combine():
Portanto, em tais casos, o uso da abordagem de "new RegExp (). Exec ()" deve ser usado apenas quando você precisa de um regex global (ou seja, para executar mais de uma vez).
exec
para obter todas as sub-seleções.+
não é necessário, poismatch
já retornará todas as subexpressões..exec
retorna apenas um de cada vez, então também não precisa disso+
.