Não sou muito bom com regex complexas.
Estou tentando escrever uma regex que encontre apenas os espaços internos de uma String, para que eu possa substituir por um único espaço.
Por exemplo:
// Ao se fazer um replace em:"Teste de regex"// deveria retornar:"Teste de regex"
// Mas se a string for:" Teste de regex "//deveria retornar:" Teste de regex "// sem fazer o trim das pontas
Fazer o replace de todos os espaços sequenciais por um único é tranquilo.
" Teste de regex ".replaceAll("\\s+"," ");
Meu problema é que eu preciso que espaços das pontas sejam ignorados.
Se alguém bom de regex puder me dar uma dica, eu ficaria muito grato
" Teste de regex ".replaceAll("\\s+"," ").replaceAll("^\\s+","").replaceAll("\\s+$","")
sf.marcius
olá entanglement,
obrigado pela força, mas eu acredito que vc não entendeu o problema.
a sua solução retira os espaços do início/ fim da string tbém (faz o trim).
Eu estou tentando remover os espaços entre palavras da frase sem que os espaços no início e no fim sejam alterados.
sf.marcius
Só para exemplificar,
hoje eu faço isso assim:
publicclassMainClass{publicstaticvoidmain(String[]args){MainClassteste=newMainClass();Stringresult=teste.middleTrim(" Teste de middle trim ");System.out.println(result);}publicStringmiddleTrim(finalCharSequencetext){PatternLR_SPACE_REGEX=Pattern.compile("^\\s+|\\s+$");PatternANY_SPACE_REGEX=Pattern.compile("\\s+");// busca espaços nas pontasMatcherlrMatcher=LR_SPACE_REGEX.matcher(text);List<Region>lrRegions=newArrayList<Region>();while(lrMatcher.find()){// mantém as regioes encontradas em ordem decrescente.lrRegions.add(0,newRegion(lrMatcher.start(),lrMatcher.end()));}// busca espaços em qquer lugarMatcheranyMatcher=ANY_SPACE_REGEX.matcher(text);List<Region>anyRegions=newArrayList<Region>();while(anyMatcher.find()){// mantém as regioes encontradas em ordem decrescente.anyRegions.add(0,newRegion(anyMatcher.start(),anyMatcher.end()));}// exclui os resultados das pontas do resultado "anywhere"anyRegions.removeAll(lrRegions);StringBuilderbuilder=newStringBuilder(text);// faz a substituicaofor(Regionregion:anyRegions){builder.replace(region.getStart(),region.getEnd()," ");}returnbuilder.toString();}staticclassRegion{privateintstart;privateintend;publicRegion(intstart,intend){this.start=start;this.end=end;}publicintgetStart(){returnstart;}publicintgetEnd(){returnend;}@OverridepublicinthashCode(){inthash=5;hash=53*hash+this.start;hash=53*hash+this.end;returnhash;}@Overridepublicbooleanequals(Objectobj){if(obj==null){returnfalse;}if(getClass()!=obj.getClass()){returnfalse;}finalRegionother=(Region)obj;if(this.start!=other.start){returnfalse;}if(this.end!=other.end){returnfalse;}returntrue;}}}
que basicamente é uma gambiarra com um pouco de teoria dos conjuntos:
busco todas as ocorrencias de espaços sequenciais (vou chamar de ANY)
busco as ocorrencias de espaços sequenciais no início e/ou fim (vou chamar de LR)
faço a subtração >> ANY - LR = MIDDLE
então faço o replace (de tras pra frente para nao invalidar as regioes encontradas).
seria interesante se houvesse um jeito de através de uma regex efetuar os passos 1, 2 e 3 de uma forma mais elegante.
E
entanglement
Ah, você NÂO quer tirar os espaços das extremidades.
Uma forma trivial de fazer isso (já que escrever expressões regulares que NÂO BATAM com alguma coisa é muito mais difícil que escrever expressões regulares que BATAM com alguma coisa) é guardar os espaços das extremidades, efetuar a troca, e depois repor os espaços.
Eu não recomendaria usar uma expressão regular que NÃO BATA com alguma coisa (que é o caso de usar “(?!X)” ou “(?<!X)” ) porque essas expressões são difíceis de escrever. De qualquer maneira, você pode tentar ver em:
isso mesmo! eu queria apenas normalizar os espaços entre palavras.
esse esquema que vc citou de recolocar os espaços é mais ou menos a idéia que implementei no algoritmo anterior.
só que ao invés de guardar o prefixo e/ou sufixo de espaços, eu guardo as coordenadas e as ignoro na substituição.
funciona. eu só estava tentando melhorá-lo utilizando apenas regex se possível.