Expressão Regular JDK 1.4

Boa noite pessoal.

Por favor como eu faço uma expressão regular pra substituir um conjunto de caracteres com um número dentro ? por exemplo:

bla bla bla bla {@322@} bla bla bla bla bla bla {@1442@} bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla

eu sempre vou ter os números 322, 1442, etc etc etc e preciso trocar esses caracteres por um texto que vou ter também, por exemplo:

322 = TEXTO1 TEXTO1 TEXTO1
1442 = TEXTO2 TEXTO2 TEXTO2

depois de executar eu preciso ter:
bla bla bla bla {@TEXTO1 TEXTO1 TEXTO1@} bla bla bla {@TEXTO2 TEXTO2 TEXTO2@}

eu tentei conforme abaixo, porém sei que não funciona:
.replaceAll("{@"+minTextosAtrib_Nivel20Elem.getIdatributo()+"@}", str)

Vamos por partes:

  • Expressões Regulares não substituem, validam (que eu saiba)…
  • E replace funcionaria para o seu exemplo.

Explica melhor o que tu quer, quem sabe eu consiga te ajudar nessa…

olá…

Eu não me lembro se o regex do java permite replace ou split.
agora estou trabalhando com regex em flex e nele existe um comando que me permite receber um array separando os
pontos que quero. no seu caso, se o regex permitir o split, vc vai precisar de uma expressão regular para encontrar o que mudar

se vc tem {@1442@}

pode encontrar totus os pontos de substituição com a seguinte expressão regular:

“{@[1-9][0-9]*@}”

[1-9][0-9]* permite que vc encontre todos os numeros de zero a infinito

dá um split nos pedaços e insere o que quer ± assim:

StringFinal = ARRAY[0] + “{@"+ VALOR_QUE_QUERO +"@}” + ARRAY[2] ;

Olá micheldf,

Eu uso bastante as expressões regulares do java. Pelo que sei, uma função pronta pra isso não existe porque nesse caso, você precisa substituir cada ocorrência por um valor diferente. Então a única maneira que conheço (e que já usei), é criar um StringBuilder para receber o texto novo e ir preenchendo-o à medida que você encontra os números na string original. Recomendo fazer isso da seguinte maneira:

1 - Crie um mapa onde as chaves são os números à serem encontrados e o valor é a string a ser colocada no lugar, ou seja, um Map<Integer, String>.

2 - Crie um java.util.regex.Pattern para encontrar qualquer número:
Pattern pattern = Pattern.compile("\d+");

3 - Crie um Matcher com a string a ser processada:
Matcher matcher = pattern.matcher(“bla bla {@322@} bla bla bla bla bla bla {@1442@} bla bla”);

4 - Use o método find do matcher para encontrar sequencialmente cada número. Cada vez que o matcher encontra sua regexp, os outros métodos do matcher irão conter informações adicionais sobre o match. Entre as que você precisa você terá os índices dos limites da string encontrada(métodos start() e end()) e a própria string (método group()), que você poderá jogar em Integer.parseInt() para obter a chave do mapa com as substituições. Com essas informações você poderá ir construindo uma cópia da string original no StringBuilder criado.

Um exemplo simples usando os métodos que você precisa:

	String bla = "sjbcdjklsnajkl76ksjhdvuk12klsdnjvld";
	Pattern pattern = Pattern.compile("\\d+");
	Matcher matcher = pattern.matcher(bla);
	while (matcher.find()) {
		System.out.print(matcher.group());
		System.out.print("\t" + matcher.start());
		System.out.println("\t" + matcher.end());
	}

Acho a API de regexp do java muito boa. É simples (tem só duas classes), poderosa e eficiente. Em particular acho eficiente porque você pode compilar expressões regulares e guardá-las numa variável estática por exemplo. A instância do objeto Pattern é quem guarda a expressão regular compilada.

Espero que ajude.

Abs,

José Roberto

Dá uma olhada aqui: http://www.guj.com.br/java/253874-voce-nao-entende-o-suporte-do-java-a-regular-expressions-eu-tb-nao-leia-isso-entao

Por que tem que usar o JDK 1.4?

A primeira opção seria substituir procurar diretamente pelo número:

        String original = "a bla {@_322_@} bla bla bla bla bla bla {@_1442_@} bla";
        String alterada = original.replaceAll("322", "TEXTO1 TEXTO1 TEXTO1")
                                .replaceAll("1442", "TEXTO2 TEXTO2 TEXTO2");

Se você precisa usar {@_ e _@} como tags para indicar os números, é só trata-los como literal na regex:

        alterada = original.replaceAll("\\{\\@\\_322\\_\\@\\}", "{@_TEXTO1 TEXTO1 TEXTO1_@}")
                                .replaceAll("\\{\\@\\_1442\\_\\@\\}", "{@_TEXTO2 TEXTO2 TEXTO2_@}");

Esse monte de \ é pq você precisa escapar os caracteres especiais na regex e no java.

Claro que com o jdk atual, o método replace, que aceita CharSequence, você colocaria diretamente as strings {@322@} e {@1442@}

No 1.4 só tinha a versão que aceitar char.

Oi AbelBueno,

Essa sugestão que você deu também funciona, mas é mais lenta porque a string é percorrida várias vezes, uma pra cada substituição, mas é mais simples de implementar.

Abs!

[quote=jrct]Oi AbelBueno,

Essa sugestão que você deu também funciona, mas é mais lenta porque a string é percorrida várias vezes, uma pra cada substituição, mas é mais simples de implementar.

Abs![/quote]

A melhor solucão é fazer uma substituicao por token, percorrendo a string várias vezes mesmo, uma vez por token. Por que vc está preocupado com velocidade aqui? Essa paranóia com performance não é justificável na grande maioria dos casos.

Então a melhor solucão é regular expressions para substituir, mas se vc quer performance pode percorrer a string e substituir na mão:

		public static void main(final String[] args) {

			final String a = "Blah blah blah _TOKEN1_ blah blah blah _TOKEN2_ blah blah";

			final Map<String, String> tokens = new HashMap<String, String>();
			tokens.put("_TOKEN1_", "whatever1");
			tokens.put("_TOKEN2_", "whatever2");

			final Set<String> keys = tokens.keySet();

			final StringBuilder sb = new StringBuilder(1024);

			for (int i = 0; i < a.length(); i++) {
				for (final String key : keys) {
					if (startsWith(a, key, i)) {
						sb.append(tokens.remove(key));
						// advance the pointer
						i += key.length();
					}
				}
				sb.append(a.charAt(i));
			}

			System.out.println(sb);

		}

		private static boolean startsWith(final String s, final String token, final int startPos) {
			int tokenIndex = 0;
			for (int i = startPos; i < s.length(); i++) {
				if (s.charAt(i) != token.charAt(tokenIndex)) {
					return false;
				}
				if (++tokenIndex == token.length()) {
					return true;
				}
			}
			return false;
		}

Colé Serginho!!!

Porque essa paranóia por performance, você pergunta? Eu pergunto porque essa aversão a se preocupar com performance? Não sabemos a aplicação que ele pretende dar ao algoritmo, pode ser um processamento de grande volume de dados, como em uma operadora de telecom por exemplo, existem muitas possibilidades. Além disso, a abordagem de processar a string repetidas vezes não tem garantia do resultado sair sempre como esperado porque cada substituição entrega para a seguinte uma versão cada vez mais diferente da original. Como consequência, pode acontecer de uma substituição criar acidentalmente uma string que se encaixe em substituições posteriores.

Acho a substituição em um passe só menos complicada de implementar e mais segura do que essa; é um meio termo entre complexidade e eficiência. Se eu fosse fazer uma substituição de cada vez, ficava com a do AbelBueno.

Abs!

José Roberto

[quote=jrct]Colé Serginho!!!

Porque essa paranóia por performance, você pergunta? Eu pergunto porque essa aversão a se preocupar com performance? Não sabemos a aplicação que ele pretende dar ao algoritmo, pode ser um processamento de grande volume de dados, como em uma operadora de telecom por exemplo, existem muitas possibilidades. Além disso, a abordagem de processar a string repetidas vezes não tem garantia do resultado sair sempre como esperado porque cada substituição entrega para a seguinte uma versão cada vez mais diferente da original. Como consequência, pode acontecer de uma substituição criar acidentalmente uma string que se encaixe em substituições posteriores.

Acho a substituição em um passe só menos complicada de implementar e mais segura do que essa; é um meio termo entre complexidade e eficiência. Se eu fosse fazer uma substituição de cada vez, ficava com a do AbelBueno.

Abs!

José Roberto[/quote]

Grande Zerinho! Agora que eu vi que é vc!

As possibilidades disso depender de performance são baixas, mas existem, concordo.

A questão da subsituicão vc tem toda razão. Por isso que eu sempre uso tokens complicados, que não vão aparecer por acidente no meio da string. Algo como TOKEN1. Nunca TOKEN1 por exemplo.

Então vc gostou da minha implementacão num passe só? Tem uma coisa que ainda dá para melhorar ali, será que alguém consegue ver?

Esse é o grande humilde mestre Zero!

Fala Sergimho!

De fato essa implementação fica bem rápida. Eu só demorei pra compreender, hehe! Não vejo onde dá pra melhorar isso não, só acho que não é bom remover as strings encontradas do mapa de tokens pois pode haver necessidade de mais substituições da mesm paalavra.

Abs,

José Roberto