Java; Remplacer la chaîne (à l'aide d'expressions régulières)?

129

Dans le cadre d'un projet pour l'école, j'ai besoin de remplacer une chaîne du formulaire:

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

à quelque chose comme:

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

Je pense que cela peut être fait avec des expressions régulières, mais je ne sais pas encore comment le faire.

Pouvez-vous me donner un coup de main?

PS La tâche réelle est d'implémenter une application Java de traitement polynomial, et je l'utilise pour passer polynomial.toString () du modèle à la vue, et je veux l'afficher à l'aide de balises html de manière jolie.

Dan Burzo
la source
2
Excusez-moi, pouvez-vous être plus précis? Je ne comprends pas ce que tu veux dire.
Dan Burzo
5
Vieille blague. codinghorror.com/blog/archives/001016.html a une explication.
Michael Myers
1
Oh :) Je pense avoir lu cet article il y a quelque temps ... Donc vous suggérez que l'expression régulière n'est pas la voie à suivre dans mon cas?
Dan Burzo
Vous n'autorisez donc que les polynômes sous forme développée?
Adam Jaskiewicz

Réponses:

176
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
la source
ah ... mais vous avez manqué de réduire le "5 * x" à "5x"
James Curran
Problèmes de couple: \ ^ doit être \\ ^ et $ doit être \ $.
cdmckay
Je reçois toujours l'erreur "séquence d'échappement invalide" ... est-ce que je manque quelque chose?
Dan Burzo
cela me donne une erreur au deuxième paramètre: str.replaceAll ("\\ ^ ([0-9] +)", "<sup> \ $ 1 </sup>"); Je ne comprends pas ... :(
Dan Burzo
2
Est-il possible d'utiliser un modèle précompilé? Cela peut être utile si vous remplacezAll par la même expression régulière plusieurs fois.
qed
38
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}
Florian
la source
8
C'est le meilleur IMO, car il utilise un Regex compilé, mais l'objet Pattern doit être un objet statique.
Marcel Valdez Orozco
La chose amusante est que la replaceAllméthode le fait implicitement Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)! Ainsi, si vous réutilisez le modèle de cette façon, les objets redondants seront évités. De plus, comme le dit @MarcelValdezOrozco, le rendre statique empêchera les invocations inutiles de compilation de modèles. :)
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
la source
11
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

veuillez noter que joindre les deux remplacements dans une seule expression régulière / remplacement serait un mauvais choix car des expressions plus générales telles que x^3 - 6 * xéchoueraient.

vit123
la source
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
la source
1
@Dan: Assurez-vous de comprendre ce que fait l'expression régulière! Les expressions régulières sont dangereuses entre les mains de personnes qui les connaissent presque . (D'où la citation que j'ai postée.)
Michael Myers
@Dan, tel quel, l'expression régulière attend un espace devant et après chaque *. Cela peut être résolu dans le regex, mais laissons cela comme un exercice.
Lieven Keersmaekers
@Dan. J'ai changé un peu l'expression régulière après avoir créé les commentaires. L'original était: (:? \ D +) * x \ ^ (:? \ D) Nouveau: (:? \ D +) * x \ ^ (:? \ D +)
Lieven Keersmaekers
3

Si c'est pour une expression mathématique générale et que les expressions entre parenthèses sont autorisées, il sera très difficile (peut-être impossible) de le faire avec des expressions régulières.

Si les seuls remplacements sont ceux que vous avez montrés, ce n'est pas si difficile à faire. Commencez par supprimer *les fichiers, puis utilisez la capture comme l'a montré Can Berk Güder pour gérer les ^.

Michael Myers
la source
Oui, j'ai expliqué plus tard dans une note PS que j'utilise ceci pour analyser une représentation sous forme de chaîne de base d'un polynôme en quelque chose de plus lisible par l'homme. Merci!
Dan Burzo
Les polynômes peuvent tous être développés sous une forme n'impliquant aucune expression entre parenthèses. Cependant, la correspondance de parent est très amusante, vous ne devriez donc pas vous limiter uniquement à une forme développée.
Adam Jaskiewicz
3

Quel est votre polynôme? Si vous le «traitez», j'envisage une sorte d'arbre de sous-expressions générées à un moment donné, et je penserais qu'il serait beaucoup plus simple de l'utiliser pour générer votre chaîne que pour réanalyser le brut expression avec une regex.

Juste jeter une autre façon de penser là-bas. Je ne suis pas sûr de ce qui se passe dans votre application.

Adam Jaskiewicz
la source
Je comprends ce que vous dites ... cela m'épargnerait en effet beaucoup de souffrance, mais j'essaie de garder les choses séparées. Je voulais que Polynomial soit une classe autonome pouvant être utilisée dans d'autres contextes, comme la console ... mais mon approche pourrait être erronée. Qu'est-ce que tu penses?
Dan Burzo
Je vois ce que tu veux dire. L'intégration des balises html dans Polynomial.toString () brise définitivement MVC. Je pense que je ferais encore quelque chose comme ça, parce que ça faciliterait vraiment les choses. Peut-être toHtmlString () ou quelque chose ...
Adam Jaskiewicz
Ou peut-être une classe distincte que la vue utilise spécifiquement pour formater le polynôme? Ensuite, la classe Polynomial elle-même n'a pas besoin de savoir quoi que ce soit sur le formatage.
Herms
j'ai créé une nouvelle méthode: toHTML (); quand on y pense, toString () et toHTML () sont fondamentalement la même chose conceptuellement, sauf qu'ils emploient des règles différentes pour le formatage;
Dan Burzo
Oui, je n'aime pas vraiment que le formatage spécifique à la vue soit dans l'objet, mais cela vous permettrait d'utiliser le polymorphisme pour gérer une grande partie de la logique plutôt qu'une instruction de commutation géante dans une méthode utilitaire statique. En fin de compte, toString () est également un formatage spécifique à la vue ...
Adam Jaskiewicz
1

Essaye ça:

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

Assurez-vous d'importer java.util.regex.

cdmckay
la source
Merci pour le conseil "import". Malheureusement, Eclipse me donne une erreur pour le deuxième paramètre: "Invalid escape sequence"
Dan Burzo
Hmmm ... Je le teste dans GroovyConsole mais pas Java. Vous devez également vous assurer que tout cela est en Java standard (c'est-à-dire créer une classe et la lancer dans une méthode principale).
cdmckay
La chaîne de remplacement doit être "<sup> $ 1 </sup>" - pas de barres obliques inverses. Groovy a des règles différentes sur les contre-obliques; vous devriez tester votre code 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);
    }
}
BigGinDaMaison
la source
0

Vous voudrez examiner la capture dans regex pour gérer l'encapsulation du 3 dans ^ 3.

Ryan Graham
la source
0

Essayez ceci, ce n'est peut-être pas la meilleure façon. mais ça marche

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);
user5915163
la source
7
La question datait de 2009 et elle a déjà 8 réponses. La première réponse a 82 voix. Votre réponse dit littéralement «peut-être pas le meilleur moyen», indiquant qu'il existe de meilleures solutions, qui existent déjà dans ce fil.
Eric G
Je ne vois pas de «meilleure» réponse au-dessus ... Il y en a une qui dans certains cas est meilleure en dessous, cependant.
sergeych
0

Jetez un œil à antlr4. Cela vous mènera beaucoup plus loin dans la création d'une structure arborescente que les seules expressions régulières.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 contient la grammaire dont vous avez besoin)

En un mot, vous définissez la grammaire pour analyser une expression, utilisez antlr pour générer du code java et ajoutez des rappels pour gérer l'évaluation lorsque l'arborescence est en cours de construction.

Geoffrey Ritchey
la source