javascript - Regex. Como obter múltiplas correspondências desta string?
Estou a usar regex em javascript. Digamos que tenho a seguinte string:
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY
e eu gostaria de executar uma regex e obter um resultado com este padrão:
Match1
1. XXX_1_XXX
2. YYY_1_YYY
Match2
1. XXX_2_XXX
2. YYY_2_YYY
Match3
1. XXX_3_XXX
2. YYY_3_YYY
Eu tentei variações disto:
/(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/g
mas ele para apenas na primeira correspondência.
Existe alguma forma de fazer isto com regex? Ou é melhor percorrê-lo como um array?
Resposta #1
Os matches são iterativos sobre a string, o regex apenas procura por mais matches após o fim do match anterior. Isto garante progresso, já que strings vazias podem resultar num ciclo infinito.
Mas podes resolver este problema da seguinte forma:
var text = "XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY";
var re = /(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/;
while((m = re.exec(text)) !== null) {
alert(JSON.stringify(m));//the result (print)
//do something with m
text = text.substring(m.index+1); //this is not the same as /g
// "/g" would be text = text.substring(m.index+m[0].length+1);
}
O programa funciona da seguinte forma: você não utiliza o modificador /g, portanto apenas uma correspondência é feita.
- A cada iteração, você tenta combinar a string com a expressão regular.
- Caso corresponda, determina o
.indexonde a correspondência começa e elimina a string (inclusive) até esse ponto - você repete a pesquisa com a cadeia modificada até que essa cadeia também não consiga encontrar convergência.
JSFiddle.
Nota: existe um caso em que isto pode falhar: se a string vazia também puder ser correspondida, pois no final da string continuará a corresponder à string vazia e o corte resultará noutra string vazia. No entanto, é fácil implementar uma verificação de comprimento zero. Este problema não se verifica com a resposta do @Ja͢ck.
Nota: outro aspeto que se deve ter em conta é que isto não requer uma progressão "global". A sequência
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_3_YYY YYY_2_YYY(repare nos valores trocados na parteYYY_|_YYY), dará o mesmo resultado.
Resposta #2
O site regex101.com é um ótimo recurso para descobrir a expressão regular correta. Preparei dois exemplos:
/([XY]{3}_[0-3]_[XY]{3})/girá retornar:
CORRESPONDÊNCIA 1
1. [0-9]XXX_1_XXX
CORRESPONDÊNCIA 2
1. [10-19]XXX_2_XXX
CORRESPONDÊNCIA 3
1. [20-29]XXX_3_XXX
CORRESPONDÊNCIA 4
1. [30-39]YYY_1_YYY
CORRESPONDÊNCIA 5
1. [40-49]YYY_2_YYY
CORRESPONDÊNCIA 6
1. [50-59]YYY_3_YYY
https://regex101.com/r/xS9eA5/1
e
/(?:([XY]{3}_[0-3]_[XY]{3}) ([XY]{3}_[0-3]_[XY]{3}))/girá retornar:
JOGO 1
1. [0-9]XXX_1_XXX
2. [10-19]XXX_2_XXX
JOGO 2
1. [20-29]XXX_3_XXX
2. [30-39]YYY_1_YYY
JOGO 3
1. [40-49]YYY_2_YYY
2. [50-59]YYY_3_YYY
https://regex101.com/r/xS9eA5/2
