【问题标题】:Java; String replace (using regular expressions)?爪哇;字符串替换(使用正则表达式)?
【发布时间】:2010-10-12 13:04:08
【问题描述】:

作为学校项目的一部分,我需要替换表单中的一个字符串:

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

类似于:

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

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

你能帮我一把吗?

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

【问题讨论】:

    标签: java regex


    【解决方案1】:
    str.replaceAll("\\^([0-9]+)", "<sup>$1</sup>");
    

    【讨论】:

    • 啊...但是您错过了将“5 * x”折叠为“5x”
    • 几个问题:\^ 需要是 \\^ 和 $ 需要是 \$。
    • 仍然收到错误“无效的转义序列”...我错过了什么吗?
    • 这给了我第二个参数的错误:str.replaceAll("\\^([0-9]+)", "\$1");我不明白... :(
    • 是否可以使用预编译模式?如果您多次使用相同的正则表达式替换所有,这可能会很有用。
    【解决方案2】:
    private String removeScript(String content) {
        Pattern p = Pattern.compile("<script[^>]*>(.*?)</script>",
                Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
        return p.matcher(content).replaceAll("");
    }
    

    【讨论】:

    • 这是最好的IMO,因为它使用了编译好的Regex,但是Pattern对象应该是静态对象。
    • 有趣的是replaceAll 方法隐式地执行Pattern.compile(regex).matcher(testString).replaceAll(regexReplacementString)!因此,如果您以这种方式重用该模式,将避免冗余对象。此外,正如@MarcelValdezOrozco 所说,将其设为静态将防止不必要的模式编译调用。 :)
    【解决方案3】:
    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>");
    

    【讨论】:

      【解决方案4】:
      "5 * x^3 - 6 * x^1 + 1".replaceAll("\\W*\\*\\W*","").replaceAll("\\^(\\d+)","<sup>$1</sup>");
      

      请注意,在单个正则表达式/替换中加入两个替换将是一个糟糕的选择,因为更通用的表达式(如 x^3 - 6 * x)会失败。

      【讨论】:

        【解决方案5】:
        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
        }
        

        【讨论】:

        • @Dan:确保您了解正则表达式的作用!正则表达式在几乎了解它们的人手中是危险的。 (因此我发布了报价。)
        • @Dan,就目前而言,正则表达式需要在每个 * 前后都有一个空格。这可以在正则表达式中解决,但让我们将其作为练习。
        • @丹。创建 cmets 后,我稍微更改了正则表达式。原来是:(:?\d+) * x\^(:?\d) 新是:(:?\d+) * x\^(:?\d+)
        【解决方案6】:

        如果这是针对任何通用数学表达式并且允许使用括号表达式,那么使用正则表达式来做到这一点将非常困难(也许是不可能的)。

        如果唯一的替代品是您展示的替代品,那么做到这一点并不难。首先去掉*'s,然后像Can Berk Güder 展示的那样使用捕获来处理^'s。

        【讨论】:

        • 是的,我后来在 P.S.请注意,我正在使用它来将多项式的基本字符串表示解析为更易于阅读的内容。谢谢!
        • 多项式都可以扩展为不包含括号表达式的形式。不过,父匹配非常有趣,因此您不应仅限于扩展形式。
        【解决方案7】:

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

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

        【讨论】:

        • 我明白你在说什么......这确实可以让我免于很多痛苦,但我试图让事情分开。我希望多项式成为一个独立的类,可以在其他上下文中使用,例如控制台......但我的方法可能是错误的。你怎么看?
        • 我明白你的意思。将 html 标签合并到 Polynomial.toString() 肯定会破坏 MVC。不过,我想我仍然会做类似的事情,因为它确实会让事情变得更容易。也许 toHtmlString() 什么的......
        • 或者可能是视图专门用于格式化多项式的单独类?那么 Polynomial 类本身就不需要知道任何有关格式的信息。
        • 我做了一个新方法:toHTML();仔细想想,toString() 和 toHTML() 在概念上基本相同,只是它们使用不同的格式规则;
        • 是的,我不太喜欢特定于视图的格式在 in 对象中,但它允许您使用多态性来处理很多逻辑而不是静态实用程序方法中的巨大 switch 语句。归根结底,toString() 也是特定于视图的格式...
        【解决方案8】:

        试试这个:

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

        一定要导入 java.util.regex。

        【讨论】:

        • 感谢“导入”提示。不幸的是,Eclipse 给了我第二个参数的错误:“无效的转义序列”
        • 嗯...我在 GroovyConsole 中测试它,但不是在 Java 中。您还必须确保这一切都在 Java 样板文件中(即创建一个类,并将其放入 main 方法中)。
        • 替换字符串应该是 "$1" - 没有反斜杠。 Groovy 对反斜杠有不同的规则;你应该用 Java 测试你的代码。
        【解决方案9】:
        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);
            }
        }
        

        【讨论】:

          【解决方案10】:

          您需要考虑在正则表达式中捕获以处理将 3 包装到 ^3 中。

          【讨论】:

            【解决方案11】:

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

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

            【讨论】:

            • 这个问题来自 2009 年,已经有 8 个答案。第一个答案有 82 票。您的回答字面意思是“可能不是最好的方法”,表明有更好的解决方案,已经在这个线程中。
            • 我在上面没有看到“更好”的答案......不过,在某些情况下,下面有一个更好的答案。
            【解决方案12】:

            看看antlr4。与单独的正则表达式相比,它会让您在创建树结构方面走得更远。

            https://github.com/antlr/grammars-v4/tree/master/calculator(calculator.g4包含你需要的语法)

            简而言之,您定义语法来解析表达式,使用 antlr 生成 java 代码,并在构建树时添加回调来处理评估。

            【讨论】:

              猜你喜欢
              • 2015-02-27
              • 1970-01-01
              • 1970-01-01
              • 2018-07-13
              • 2015-11-30
              • 2021-11-29
              相关资源
              最近更新 更多