Extrair palavras de uma frase com REGEX e método split da classe String

Preciso mapear os tokens (palavras) de dada frase para um array de String mas não sei como utilizar uma regexp correta para splitar corretamente para o array. Do jeito que fiz, ele pega o espaço em branco pós-separadores (vírgulas, dois-pontos e afins) e considera como um token também. Fiz uma “gambiarra” para corrigir.

Fiz o seguinte:

public class MapeadoraFrase {
	private static final String REGEX = "\\,|\\;|\\:|\\.|\\?|\\!|\\ ";	
	private String frase;
	private String[] tokens;
	private Map<Integer, Character> separadores;
	
	public MapeadoraFrase(String frase) {
		tokens = frase.split(REGEX);
		
		for (int i=0; i < tokens.length; i++)
			tokens[i] = tokens[i].replaceAll(" ", "");
	}
	
	public void exibirTokens() {
		for (int i = 0; i < tokens.length; i++)
			Main.print(String.format("[%d] \'%s\'", i, tokens[i]));
	}
		
}

Classe do main:

[code]public class Main {

/**
 * @param args
 */
public static void main(String[] args) {
	new MapeadoraFrase("Esta, é uma frase: a ser tokenizada.").exibirTokens();
}

public static void print(Object obj) {
	System.out.println(obj);
}

}
[/code]

Note que, ao comentar o “FOR” do construtor os espaços em branco são considerados como palavras e vão para o array. Como filtro isso sem gambiarras?

Grato desde já.

Mude a regex.

Eu escreveria sua regex como:

"[ ,;:.?!]+"

Obrigado pela resposta. E outra pergunta: como splitar um texto em frases? Como dá pra ver, não sei nada de regex.

Grato.

O que é uma frase para você?

  • É algo que termina em um ponto final, ou um ponto de interrogação, ou um ponto de exclamação. O único problema é que abreviaturas, como “sr. Junqueira”, teriam que ser identificadas para não terminar indevidamente uma frase.
  • Não se esqueça que na história dos pontos, você tem de considerar as devidas combinações dos pontos. Por exemplo:

Era uma vez… Você é do tempo em que os animais falavam!!!

Ou seja, provavelmente sua expressão regular será algo como:

"[.!?]+"

Como se vê, mais importante que saber regex, é saber definir o problema. Mesmo um problema aparentemente simples como “separar um texto em frases” é na verdade algo que deve ser bem definido, e talvez acabe sendo mais complicado que parece, e não seja fácil de resolver só com expressões regulares. Por exemplo, a expressão regular que lhe passei não cuida do caso das abreviaturas, o que irá causar problemas.

Só para ter uma ideia, se você usar as expressões regulares e split para separar as frases, você perderá os pontos

Por exemplo, naquele exemplo que lhe passei:

"Era uma vez… Você é do tempo em que os animais falavam!!! "

Você teria o seguinte array de strings:

“Era uma vez”
" Você é do tempo em que os animais falavam"
" "

Ou seja, você perde os pontos :frowning:

É melhor usar Pattern, Matcher e os métodos find e group da classe Matcher, assim não perderá os pontos, entretanto dá um pouco mais de trabalho.