180

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.

Tim
  • 34,733
  • 11
  • 90
  • 118
Dan Burzo
  • 9,572
  • 18
  • 46
  • 69

12 Answers12

226
str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
Can Berk Güder
  • 104,295
  • 25
  • 128
  • 136
53
private String removeScript(String content) {
    Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
    return p.matcher(content).replaceAll("");
}
Florian
  • 531
  • 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
12
"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
  • 6,676
  • 2
  • 21
  • 42
vit123
  • 121
  • 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,179
  • 8
  • 18
Lieven Keersmaekers
  • 55,505
  • 12
  • 105
  • 142
  • 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
  • 184,092
  • 45
  • 284
  • 291
  • 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 Burzo 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,860
  • 3
  • 33
  • 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 Burzo 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 Burzo 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,179
  • 8
  • 18
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,047
  • 22
  • 82
  • 113
  • Thanks for the 'import' tip. Unfortunately, Eclipse gives me an error for the second parameter: "Invalid escape sequence" – Dan Burzo 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);
  • 7
    The question was from 2009 and it has 8 answers already. The first answer has 82 votes. Your answer literally says 'may not be the best way' indicating there are better solutions, which there are, already in this thread. – Eric G Feb 18 '16 at 13:11
  • I see no 'better' answer above it... There is one that in some cases is better below, though. – sergeych Dec 12 '16 at 14:33
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.

Ryan Graham
  • 7,808
  • 2
  • 28
  • 32