Java; Substituição de string (usando expressões regulares)?


128

Como parte de um projeto para a escola, preciso substituir uma sequência do formulário:

5 * x^3 - 6 * x^1 + 1

para algo como:

5x<sup>3</sup> - 6x<sup>1</sup> + 1

Acredito que isso possa ser feito com expressões regulares, mas ainda não sei como fazê-lo.

Você pode me ajudar?

PS: A atribuição real é implementar um aplicativo Java de Polynomial Processing, e estou usando isso para passar polynomial.toString () do modelo para a visualização, e quero exibi-lo usando tags html de uma maneira bonita.


2
Com licença, você pode ser mais específico? Eu não entendo o que você quer dizer.
22909 Dan Burzo

5
Piada velha. codinghorror.com/blog/archives/001016.html tem uma explicação.
Michael Myers

1
Ah :) Acho que realmente li esse artigo há algum tempo ... Então você está sugerindo que o regex não é o caminho a seguir no meu caso?
22909 Dan Burzo

Então, você está permitindo apenas polinômios na forma expandida?
23611 Adam Jaskiewicz

Respostas:


175
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");

ah ... mas você perdeu o colapso do "5 * x" para "5x"
James Curran

Problemas de casal: \ ^ precisa ser \\ ^ e $ precisa ser \ $.
Cdmckay 10/03/09

Ainda estou recebendo o erro "sequência de escape inválida" ... estou perdendo alguma coisa?
22909 Dan Burzo

isso me dá um erro no segundo parâmetro: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); Eu não entendo isso ... :(
Dan Burzo

2
É possível usar um padrão pré-compilado? Isso pode ser útil se você substituirAll pelo mesmo regex várias vezes.
qed

38
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}

8
Este é o melhor IMO, porque usa um Regex compilado, mas o objeto Pattern deve ser um objeto estático.
Marcel Valdez Orozco

O engraçado é que o replaceAllmétodo implica implicitamente Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Portanto, se você reutilizar o padrão dessa maneira, objetos redundantes serão evitados. Além disso, como diz @MarcelValdezOrozco, torná-lo estático impedirá invocações desnecessárias de compilação de padrões. :)
varun

20
String input = "hello I'm a java dev" +
"no job experience needed" +
"senior software engineer" +
"java job available for senior software engineer";

String fixedInput = input.replaceAll("(java|job|senior)", "<b>$1</b>");

10
import java.util.regex.PatternSyntaxException;

// (:?\d+) \* x\^(:?\d+)
// 
// Options: ^ and $ match at line breaks
// 
// Match the regular expression below and capture its match into backreference number 1 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the character “ ” literally « »
// Match the character “*” literally «\*»
// Match the characters “ x” literally « x»
// Match the character “^” literally «\^»
// Match the regular expression below and capture its match into backreference number 2 «(:?\d+)»
//    Match the character “:” literally «:?»
//       Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
//    Match a single digit 0..9 «\d+»
//       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
try {
    String resultString = subjectString.replaceAll("(?m)(:?\\d+) \\* x\\^(:?\\d+)", "$1x<sup>$2</sup>");
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
} catch (IllegalArgumentException ex) {
    // Syntax error in the replacement text (unescaped $ signs?)
} catch (IndexOutOfBoundsException ex) {
    // Non-existent backreference used the replacement text
}

1
@ Dan: Certifique-se de entender o que a regex está fazendo! Regexes são perigosos nas mãos de pessoas que quase os conhecem. (Daí a citação que eu publiquei.)
Michael Myers

@ Dan, como está, o regex espera um espaço na frente e depois de cada *. Isso pode ser resolvido no regex, mas vamos deixar isso como um exercício.
Lieven Keersmaekers #

@Dan. Mudei o regex um pouco depois de criar os comentários. O original era: (:? \ D +) * x \ ^ (:? \ D) O novo é: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers #

10
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

observe que unir as duas substituições em uma única regex / substituição seria uma péssima escolha, pois expressões mais gerais, como x^3 - 6 * xfalhariam.


3

Se isso for para qualquer expressão matemática geral e expressões entre parênteses forem permitidas, será muito difícil (talvez impossível) fazer isso com expressões regulares.

Se as únicas substituições são as que você mostrou, não é tão difícil de fazer. Primeiro *tire as roupas e depois use como Can Berk Güder mostrou para lidar com as roupas ^.


Sim, expliquei posteriormente em uma nota do PS que estou usando isso para analisar uma representação básica de cadeia de um polinômio em algo mais legível por humanos. Obrigado!
22909 Dan Burzo

Todos os polinômios podem ser expandidos para um formulário que não envolve expressões entre parênteses. A correspondência de parênteses é muito divertida; portanto, você não deve se limitar apenas à forma expandida.
23811 Adam Jaskiewicz

3

Qual é o seu polinômio? Se você está "processando", estou imaginando algum tipo de árvore de sub-expressão sendo gerada em algum momento e pensaria que seria muito mais simples usar isso para gerar sua string do que analisar novamente a matéria-prima expressão com um regex.

Apenas lançando uma maneira diferente de pensar lá fora. Não tenho certeza do que mais está acontecendo no seu aplicativo.


Entendo o que você está dizendo ... isso realmente me pouparia muito sofrimento, mas estou tentando manter as coisas separadas. Queria que o Polynomial fosse uma classe autônoma que possa ser usada em outro contexto, como o console ... mas minha abordagem pode estar errada. O que você acha?
22909 Dan Burzo

Eu vejo o que você quer dizer. Incorporar as tags html no Polynomial.toString () definitivamente está quebrando o MVC. Acho que ainda faria algo assim, porque realmente tornaria as coisas mais fáceis. Talvez toHtmlString () ou algo assim ...
Adam Jaskiewicz

Ou talvez uma classe separada que o View use especificamente para formatar o polinômio? Então a própria classe Polynomial não precisa saber nada sobre a formatação.
Herms

Eu criei um novo método: toHTML (); quando você pensa sobre isso, toString () e toHTML () são basicamente a mesma coisa conceitualmente, exceto que empregam regras diferentes para formatação;
22909 Dan Burzo

Sim, eu realmente não gosto que a formatação específica da visualização esteja no objeto, mas permitiria que você usasse o polimorfismo para lidar com grande parte da lógica, em vez de uma declaração de switch gigante em um método de utilidade estática. Quando se trata baixo direito a ela, toString () também é vista específico formatação ...
Adam Jaskiewicz

1

Tente o seguinte:

String str = "5 * x^3 - 6 * x^1 + 1";
String replacedStr = str.replaceAll("\\^(\\d+)", "<sup>\$1</sup>");

Certifique-se de importar o java.util.regex.


Obrigado pela dica 'importar'. Infelizmente, o Eclipse me deu um erro para o segundo parâmetro: "Sequência de escape inválida" #
2200 Dan Burzo

Hmmm ... Eu testo no GroovyConsole, mas não no Java. Você também precisa se certificar de que tudo isso esteja em Java clichê (por exemplo, faça uma classe e jogue-a no método principal).
Cdmckay 10/03/09

A cadeia de substituição deve ser "<sup> $ 1 </sup>" - sem barras invertidas. O Groovy possui regras diferentes sobre barras invertidas; você deve testar seu código em Java.
Alan Moore

1
class Replacement 
{
    public static void main(String args[])
    {
        String Main = "5 * x^3 - 6 * x^1 + 1";
        String replaced = Main.replaceAll("(?m)(:?\\d+) \\* x\\^(:?\\d+)", "$1x<sup>$2</sup>");
        System.out.println(replaced);
    }
}

0

Você deseja analisar a captura em regex para manipular a quebra de 3 em ^ 3.


0

Tente isso, pode não ser o melhor caminho. mas funciona

String str = "5 * x^3 - 6 * x^1 + 1";
str = str.replaceAll("(?x)(\\d+)(\\s+?\\*?\\s+?)(\\w+?)(\\^+?)(\\d+?)", "$1$3<sup>$5</sup>");
System.out.println(str);

7
A pergunta era de 2009 e já tem 8 respostas. A primeira resposta tem 82 votos. Sua resposta literalmente diz 'pode não ser o melhor caminho', indicando que existem soluções melhores, que já existem neste segmento.
Eric G

Não vejo resposta 'melhor' acima dela ... Mas há uma que, em alguns casos, é melhor abaixo.
Sergeych

0

Dê uma olhada no antlr4. Isso o levará muito mais longe na criação de uma estrutura em árvore do que apenas expressões regulares.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 contém a gramática necessária)

Em poucas palavras, você define a gramática para analisar uma expressão, usa o antlr para gerar código java e adiciona retornos de chamada para lidar com a avaliação quando a árvore está sendo construída.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.