Java; Reemplazo de cadena (usando expresiones regulares)?

129

Como parte de un proyecto para la escuela, necesito reemplazar una cadena del formulario:

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

a algo como:

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

Creo que esto se puede hacer con expresiones regulares, pero aún no sé cómo hacerlo.

¿Me puedes echar una mano?

PD La asignación real es implementar una aplicación Java de procesamiento de polinomios, y estoy usando esto para pasar polynomial.toString () del modelo a la vista, y quiero mostrarlo usando etiquetas html de una manera bonita.

Dan Burzo
fuente
2
Disculpe, ¿puede ser más específico? No entiendo lo que quieres decir.
Dan Burzo
55
Broma vieja codinghorror.com/blog/archives/001016.html tiene una explicación.
Michael Myers
1
Oh :) Creo que en realidad leí ese artículo hace un tiempo ... ¿Entonces estás sugiriendo que la expresión regular no es el camino a seguir en mi caso?
Dan Burzo
¿Entonces solo está permitiendo polinomios en forma expandida?
Adam Jaskiewicz

Respuestas:

176
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
fuente
ah ... pero te perdiste colapsar el "5 * x" a "5x"
James Curran
Problemas de pareja: \ ^ debe ser \\ ^ y $ debe ser \ $.
cdmckay
Todavía obtengo el error "secuencia de escape no válida" ... ¿me falta algo?
Dan Burzo
esto me da un error en el segundo parámetro: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); No lo entiendo ... :(
Dan Burzo
2
¿Es posible usar un patrón precompilado? Esto podría ser útil si reemplaza All con la misma expresión regular muchas veces.
qed
38
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}
Florian
fuente
8
Esta es la mejor OMI, porque utiliza una expresión regular compilada, pero el objeto Patrón debería ser un objeto estático.
Marcel Valdez Orozco
¡Lo divertido es que el replaceAllmétodo lo hace implícitamente Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Por lo tanto, si reutiliza el patrón de esta manera, se evitarán los objetos redundantes. Además, como dice @MarcelValdezOrozco, hacerlo estático evitará invocaciones innecesarias de compilación de patrones. :)
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>");
Hubbison
fuente
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
}
Lieven Keersmaekers
fuente
1
@Dan: ¡Asegúrate de entender lo que está haciendo la expresión regular! Las expresiones regulares son peligrosas en manos de personas que casi las conocen. (De ahí la cita que publiqué.)
Michael Myers
@Dan, tal como está, la expresión regular espera un espacio delante y después de cada *. Esto se puede resolver en la expresión regular, pero dejemos eso como un ejercicio.
Lieven Keersmaekers
@Dan. Cambié la expresión regular un poco después de crear los comentarios. Original era: (:? \ D +) * x \ ^ (:? \ D) Nuevo es: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers
10
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

tenga en cuenta que unir ambos reemplazos en una sola expresión regular / reemplazo sería una mala elección porque las expresiones más generales como x^3 - 6 * xfallarían.

vit123
fuente
3

Si esto es para cualquier expresión matemática general y se permiten expresiones entre paréntesis, será muy difícil (quizás imposible) hacerlo con expresiones regulares.

Si los únicos reemplazos son los que mostró, no es tan difícil de hacer. Primero *elimine los 's, luego use la captura como mostró Can Berk Güder para manejar los ^' s.

Michael Myers
fuente
Sí, luego expliqué en una nota de PS que estoy usando esto para analizar una representación de cadena básica de un polinomio en algo más legible para los humanos. ¡Gracias!
Dan Burzo
Todos los polinomios pueden expandirse a una forma que no implique expresiones entre paréntesis. Sin embargo, la combinación de paren es muy divertida, por lo que no debe limitarse solo a la forma expandida.
Adam Jaskiewicz
3

¿Cuál es tu polinomio? Si lo está "procesando", estoy imaginando que se generará algún tipo de árbol de subexpresiones en algún momento, y pensaría que sería mucho más simple usar eso para generar su cadena que volver a analizar el raw expresión con una expresión regular.

Simplemente lanzando una forma diferente de pensar por ahí. No estoy seguro de qué más está pasando en su aplicación.

Adam Jaskiewicz
fuente
Entiendo lo que estás diciendo ... eso realmente me ahorraría mucho sufrimiento, pero estoy tratando de mantener las cosas separadas. Quería que Polynomial fuera una clase independiente que se pueda utilizar en otro contexto, como la consola ... pero mi enfoque podría ser incorrecto. ¿Qué piensas?
Dan Burzo
Veo a que te refieres. Incorporar las etiquetas html en Polynomial.toString () definitivamente está rompiendo MVC. Sin embargo, creo que aún haría algo así, porque realmente facilitaría las cosas. Quizás toHtmlString () o algo así ...
Adam Jaskiewicz
¿O tal vez una clase separada que la Vista usa específicamente para formatear el polinomio? Entonces la clase Polynomial en sí misma no necesita saber nada sobre el formato.
Herms
Hice un nuevo método: toHTML (); Cuando lo piensas, toString () y toHTML () son básicamente lo mismo conceptualmente, excepto que emplean diferentes reglas para formatear;
Dan Burzo
Sí, realmente no me gusta que el formato específico de la vista esté en el objeto, pero le permitiría usar el polimorfismo para lidiar con mucha lógica en lugar de una declaración de interruptor gigante en un método de utilidad estática. Cuando se trata de eso, toString () también es un formato específico de vista ...
Adam Jaskiewicz
1

Prueba esto:

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

Asegúrese de importar java.util.regex.

cdmckay
fuente
Gracias por el consejo de 'importación'. Desafortunadamente, Eclipse me da un error para el segundo parámetro: "Secuencia de escape no
válida
Hmmm ... Lo pruebo en GroovyConsole pero no en Java. También debe asegurarse de que todo esto esté en Java repetitivo (es decir, hacer una clase y arrojarla en un método principal).
cdmckay
La cadena de reemplazo debe ser "<sup> $ 1 </sup>", sin barras invertidas. Groovy tiene diferentes reglas sobre barras invertidas; deberías probar tu código en 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);
    }
}
BigGinDaHouse
fuente
0

Querrá examinar la captura en expresiones regulares para manejar envolver el 3 en ^ 3.

Ryan Graham
fuente
0

Prueba esto, puede que no sea la mejor manera. pero 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);
usuario5915163
fuente
77
La pregunta era de 2009 y ya tiene 8 respuestas. La primera respuesta tiene 82 votos. Su respuesta literalmente dice 'puede que no sea la mejor manera', lo que indica que hay mejores soluciones, que ya existen, en este hilo.
Eric G
No veo una respuesta 'mejor' por encima ... Sin embargo, hay una que en algunos casos es mejor a continuación.
sergeych
0

Echa un vistazo a antlr4. Te llevará mucho más lejos en la creación de una estructura de árbol que las expresiones regulares solas.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 contiene la gramática que necesita)

En pocas palabras, usted define la gramática para analizar una expresión, usa antlr para generar código java y agrega devoluciones de llamada para manejar la evaluación cuando se está construyendo el árbol.

Geoffrey Ritchey
fuente