Java; 字符串替换(使用正则表达式)?


128

作为学校项目的一部分,我需要替换以下形式的字符串:

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

像这样:

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

我相信可以使用正则表达式来完成此操作,但是我还不知道该怎么做。

你能帮我一下吗?

PS实际的任务是实现一个多项式处理Java应用程序,并且我正在使用它来将polynomial.toString()从模型传递到视图,并且希望使用html标记以一种漂亮的方式显示它。


2
不好意思,您能说得更具体些吗?我不明白你的意思。
丹·伯佐


1
哦:)我想我实际上早就读过该文章了。。。。。。。
丹·伯佐

因此,您只允许扩展形式的多项式吗?
亚当·贾斯基维奇

Answers:


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

啊...但是您错过了将“ 5 * x”折叠为“ 5x”的问题
James Curran

几个问题:\ ^必须是\\ ^,而$必须是\ $。
cdmckay,2009年

仍然出现错误“无效的转义序列” ...我缺少什么吗?
丹·伯佐

这给我第二个参数错误:str.replaceAll(“ \\ ^([0-9] +)”,“ <sup> \ $ 1 </ sup>”); 我不明白... :(
丹·伯佐

2
是否可以使用预编译模式?如果您多次使用相同的正则表达式替换All,这可能会很有用。
2014年

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

8
这是最好的IMO,因为它使用了已编译的Regex,但是Pattern对象应该是静态对象。
马塞尔·瓦尔德兹·奥罗斯科

有趣的是,该replaceAll方法可以隐式执行Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)!因此,如果您以这种方式重复使用模式,将避免多余的对象。此外,正如@MarcelValdezOrozco所说,将其设置为静态将防止不必要的模式编译调用。:)
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:确保您了解正则表达式在做什么!正则表达式在几乎认识它们的人手中很危险。(因此,我发表了报价。)
迈克尔·迈尔斯

@Dan,正则表达式,正则表达式期望每个*前后都有一个空格。这可以在正则表达式中解决,但让我们将其作为练习。
Lieven Keersmaekers,2009年

@担。创建评论后,我对正则表达式做了一些更改。原为:(:?\ d +)* x \ ^(:?\ d)新为:(:?\ d +)* x \ ^(:?\ d +)
Lieven Keersmaekers,2009年

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

请注意,将两个替换项合并到一个正则表达式/替换中将是一个糟糕的选择,因为诸如此类的更通用的表达式x^3 - 6 * x会失败。


3

如果这适用于任何通用数学表达式,并且允许使用括号表达式,则使用正则表达式将非常困难(也许不可能)。

如果唯一的替代品是您所展示的替代品,那就不难做到。首先*去掉,然后使用Can BerkGüder所示的捕获来处理^


是的,我稍后在PS注释中解释说,我正在使用它将多项式的基本字符串表示形式解析为更易于理解的内容。谢谢!
丹·伯佐

多项式都可以扩展为不包含括号表达式的形式。Paren匹配非常有趣,因此您不应该只限于扩展形式。
亚当·贾斯基维奇

3

你的多项式是多少?如果您正在“处理”它,那么我会预想在某个时候会生成某种形式的子表达式树,并且认为使用它来生成字符串比重新解析原始字符串要简单得多。用正则表达式表达。

只是抛出一种不同的思考方式。我不确定您的应用中还发生了什么。


我了解您在说什么……的确可以让我免除很多痛苦,但是我正在努力使事情分开。我希望Polynomial是一个独立的类,可以在其他环境(例如控制台)中使用...但是我的方法可能是错误的。你怎么看?
丹·伯佐

我明白你的意思了。将html标记合并到Polynomial.toString()中肯定会破坏MVC。我想我仍然会做类似的事情,因为这确实会使事情变得容易。也许toHtmlString()之类的东西
亚当·贾斯基维奇

还是View专门用于格式化多项式的单独类?然后,多项式类本身不需要了解任何格式。
Herms,2009年

我做了一个新方法:toHTML(); 当您考虑时,toString()和toHTML()在概念上基本上是相同的,只是它们使用不同的格式规则;
丹·伯佐

是的,我真的不喜欢特定于视图的格式包含对象中,但是它将允许您使用多态来处理很多逻辑,而不是在静态实用程序方法中使用巨大的switch语句。说到它,toString()也是特定于视图的格式...
Adam Jaskiewicz,2009年

1

试试这个:

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

确保导入java.util.regex。


感谢您的“导入”提示。不幸的是,Eclipse给了我第二个参数错误:“无效的转义序列”
Dan Burzo,2009年

嗯...我在GroovyConsole中测试了它,但是没有在Java中测试过。您还必须确保所有这些都在Java样板文件中(即创建一个类,并将其扔到main方法中)。
cdmckay

替换字符串应为“ <sup> $ 1 </ sup>”-无反斜杠。Groovy对于反斜杠有不同的规则。您应该使用Java测试您的代码。
艾伦·摩尔

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

试试这个,可能不是最好的方法。但是有效

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
问题来自2009年,已经有8个答案。第一个答案有82票。您的回答字面意思是“可能不是最好的方法”,表明此线程中已有更好的解决方案。
埃里克·G

我看不到上面有“更好”的答案……不过,在某些情况下,下面的答案更好。
sergeych

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.