197

As part of a project for school, I need to replace a string from the form:

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

to something like:

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

I believe this can be done with regular expressions, but I don't know how to do it yet.

Can you lend me a hand?

P.S. The actual assignment is to implement a Polynomial Processing Java application, and I'm using this to pass polynomial.toString() from the model to the view, and I want do display it using html tags in a pretty way.

xpt
  • 20,363
  • 37
  • 127
  • 216
Dan
  • 9,912
  • 18
  • 49
  • 70
  • Note that this is a school project, and most answers missed collapsing the "5 * x" to "5x". I.e., the question is actually not about string replacement, but the actual assignment is to implement a Polynomial Processing Java application. – xpt Dec 15 '22 at 15:24

12 Answers12

247
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
  • 109,922
  • 25
  • 130
  • 137
  • ah... but you missed collapsing the "5 * x" to "5x" – James Curran Mar 10 '09 at 20:53
  • Couple problems: \^ needs to be \\^ and $ needs to be \$. – cdmckay Mar 10 '09 at 21:00
  • Still getting error "invalid escape sequence" ... am i missing something? – Dan Mar 10 '09 at 21:03
  • this gives me an error at the second parameter: str.replaceAll("\\^([0-9]+)", "\$1"); I don't get it... :( – Dan Mar 10 '09 at 21:10
  • You need another backslash before the $. – Michael Myers Mar 10 '09 at 21:14
  • No, there shouldn't be any backslashes in the replacement string. – Alan Moore Mar 11 '09 at 11:22
  • @Alan M: Heh, you're right. Another backslash would allow it to compile, but it wouldn't do anything useful. – Michael Myers Mar 11 '09 at 15:42
  • 3
    Is it possible to use a precompiled pattern? This might be useful if you do replaceAll with the same regex many times. – qed Nov 05 '14 at 20:35
  • How about adding a link to the reference documentation. Simply answering with a single line of code is not particularly helpful. – LintfordPickle Jul 13 '18 at 13:52
  • I tried this code it literally does nothing for the string in the question. – GC_ Jun 18 '21 at 21:22
  • Comments here are also capable to include links, f.e. [to the documentation of `.replaceAll()`](https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll(java.lang.String,%20java.lang.String)). @GC_ It replaces `^3` with `3` - keep in mind you have to use the result of that - it doesn't manipulate `str` itself - you have to re-assign the result to something. – AmigoJack Oct 07 '22 at 10:52
58
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}
Florian
  • 581
  • 4
  • 2
  • 10
    This is the best IMO, because it uses a compiled Regex, but the Pattern object should be a static object. – Marcel Valdez Orozco May 27 '16 at 15:42
  • 3
    Fun thing is that the `replaceAll` method implicitly does `Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)`! So, if you re-use the pattern this way, redundant objects will be avoided. Further, as @MarcelValdezOrozco says, making it static will prevent unnecessary pattern compile invocations. :) – varun Aug 30 '19 at 18:18
23
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
  • 231
  • 2
  • 2
13
"5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");

please note that joining both replacements in a single regex/replacement would be a bad choice because more general expressions such as x^3 - 6 * x would fail.

CollinD
  • 7,304
  • 2
  • 22
  • 45
vit123
  • 131
  • 1
  • 5
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
}
BigGinDaHouse
  • 1,282
  • 9
  • 19
Lieven Keersmaekers
  • 57,207
  • 13
  • 112
  • 146
  • 1
    @Dan: Be sure you understand what the regex is doing! Regexes are dangerous in the hands of people who *almost* know them. (Hence the quote I posted.) – Michael Myers Mar 10 '09 at 21:13
  • @Dan, as it stands, the regex expects a space in front of and after each *. This can be solved in the regex but let's leave that as an excercise. – Lieven Keersmaekers Mar 10 '09 at 21:13
  • @Dan. I changed the regex a bit after creating the comments. Original was: (:?\d+) \* x\^(:?\d) New is: (:?\d+) \* x\^(:?\d+) – Lieven Keersmaekers Mar 10 '09 at 21:19
3

If this is for any general math expression and parenthetical expressions are allowed, it will be very difficult (perhaps impossible) to do this with regular expressions.

If the only replacements are the ones you showed, it's not that hard to do. First strip out *'s, then use capturing like Can Berk Güder showed to handle the ^'s.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
  • Yes, I later explained in a P.S. note that I'm using this to parse a basic string representation of a polynomial into something more human readable. Thanks! – Dan Mar 10 '09 at 20:57
  • Polynomials can all be expanded to a form involving no parenthetical expressions. Paren-matching is great fun, though, so you shouldn't limit yourself to expanded form only. – Adam Jaskiewicz Mar 10 '09 at 21:37
3

What is your polynomial? If you're "processing" it, I'm envisioning some sort of tree of sub-expressions being generated at some point, and would think that it would be much simpler to use that to generate your string than to re-parse the raw expression with a regex.

Just throwing a different way of thinking out there. I'm not sure what else is going on in your app.

Adam Jaskiewicz
  • 10,934
  • 3
  • 34
  • 37
  • I understand what you're saying... that would indeed spare me a lot of suffering, but I'm trying to keep things separate. I wanted Polynomial to be a stand-alone Class that can be used in other context, such as the console... but my approach might be wrong. What do you think? – Dan Mar 10 '09 at 21:07
  • I see what you mean. Incorporating the html tags into Polynomial.toString() is definitely breaking MVC. I think I would still do something like that, though, because it really would make things easier. Perhaps toHtmlString() or something... – Adam Jaskiewicz Mar 10 '09 at 21:11
  • Or maybe a separate class that the View uses specifically for formatting the polynomial? Then the Polynomial class itself doesn't need to know anything about the formatting. – Herms Mar 10 '09 at 21:20
  • i made a new method: toHTML(); when you think about it, toString() and toHTML() are basically the same thing conceptually, except they employ different rules for formatting; – Dan Mar 10 '09 at 21:26
  • Yeah, I don't really like that the view-specific formatting is *in* the object, but it would allow you to use polymorphism to deal with a lot of the logic rather than a giant switch statement in a static utility method. When it comes right down to it, toString() is also view-specific formatting... – Adam Jaskiewicz Mar 10 '09 at 21:48
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
  • 1,282
  • 9
  • 19
1

Try this:

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

Be sure to import java.util.regex.

cdmckay
  • 31,832
  • 25
  • 83
  • 114
  • Thanks for the 'import' tip. Unfortunately, Eclipse gives me an error for the second parameter: "Invalid escape sequence" – Dan Mar 10 '09 at 21:01
  • Hmmm... I test it in GroovyConsole but not Java. You also have to make sure that this is all in Java boilerplate (i.e. make a class, and throw it in a main method). – cdmckay Mar 10 '09 at 21:02
  • The replacement string should be "$1" - no backslashes. Groovy has different rules about backslashes; you should test your code in Java. – Alan Moore Mar 11 '09 at 11:28
0

Try this, may not be the best way. but it works

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);
0

Take a look at antlr4. It will get you much farther along in creating a tree structure than regular expressions alone.

https://github.com/antlr/grammars-v4/tree/master/calculator (calculator.g4 contains the grammar you need)

In a nutshell, you define the grammar to parse an expression, use antlr to generate java code, and add callbacks to handle evaluation when the tree is being built.

0

You'll want to look into capturing in regex to handle wrapping the 3 in ^3.

Ryann Graham
  • 8,079
  • 2
  • 29
  • 32