【问题标题】:How do I extract this string using a regular expression in Java?如何使用 Java 中的正则表达式提取此字符串?
【发布时间】:2009-05-15 18:15:54
【问题描述】:
errorString="AxisFault\n
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException\n
 faultSubcode: \n
 faultString: My Error\n
 faultActor: \n
 faultNode: \n
 faultDetail: \n
    {}string: this is the fault detail"


Pattern pattern = Pattern.compile(".*faultString(.*)", Pattern.DOTALL);
Matcher matcher = pattern.matcher(errorString);
if (matcher.matches()) {
   String match = matcher.group(1);
   return match;
}

我想得到“我的错误”,但它返回到整个字符串的末尾,而不是匹配到 faultString 行末尾的 \n。我尝试了很多技术让它在行尾停止,但没有成功。

谢谢

【问题讨论】:

    标签: java regex


    【解决方案1】:

    你不应该传递Pattern.DOTALL;这会导致换行符与.* 匹配,而这正是您想要的。

    更好的正则表达式是:

    Pattern pattern = Pattern.compile("faultString: (.*)");
    

    然后,而不是matcher.matches(),使用find() 来查看它是否出现在字符串中的任何位置。

    还请注意,我已将正则表达式修改为仅对“我的错误”部分进行分组,而不是像原来的那样对“:我的错误”部分进行分组。

    为了清楚起见,这是我测试的代码:

    Pattern pattern = Pattern.compile("faultString: (.*)");
    Matcher matcher = pattern.matcher(errorString);
    if (matcher.find()) {
        System.out.println(matcher.group(1));
    }
    

    errorString 与您的相同。
    输出是:

    我的错误

    【讨论】:

    • 这就是我要找的。不过仍然很好奇如何使它与匹配项一起使用。
    • 如果使用matches(),您可以将“.*faultString: ([^\\n]*).*”与Pattern.DOTALL 一起使用,如Chris Thornhill 和Mike Digdon 所述。
    • 但如果可以的话,我不喜欢使用无关的点(请参阅 Jan Goyvaerts 的文章 regular-expressions.info/dot.html )。在这种情况下,它不会有所作为,但为了将来参考,只需尝试匹配您需要的内容。 (此外,我更愿意将 Pattern 对象拉出到静态最终变量中,以避免在每次调用时重新编译它。)
    • 了解 Matcher.matches() 和 Matcher.find() 之间的区别很重要。 matches 方法尝试将整个输入序列与模式进行匹配。除非模式从头到尾匹配整个字符串,否则它不会返回 true。这通常与 ^ 和 $ 一起使用来表示字符串的开头和结尾。 find 方法扫描输入序列,寻找与模式匹配的下一个子序列。如果模式出现在字符串中的任何位置,它将返回 true。
    【解决方案2】:

    我可能会将 Chris 的正则表达式清理为以下内容:".*faultString:\\s*([^\\n]*).*"

    【讨论】:

      【解决方案3】:
      Pattern pattern = Pattern.compile("^faultString(.*)$", Pattern.MULTILINE);
      

      【讨论】:

      • ^faultString 会造成麻烦;看起来有一个领先的空间。 "\\bfaultString: .*$" 怎么样? +1 为 Pattern.MULTILINE 无论如何;这是关键。
      • 其实关键是用find()而不是matches()。
      【解决方案4】:

      这看起来像属性文件格式。使用StringReader 将此字符串加载到java.util.Property 然后从中读取会更容易吗?

      【讨论】:

      • 我试图强迫自己通过使用正则表达式来解决字符串解析问题一段时间,这样我实际上可以更好地学习正则表达式。我很少使用它们,但想做得更好。我当然可以通过其他方法更快地解决这个问题,但我想扩展我的技能..
      【解决方案5】:

      这适用于 .matches() 方法:

      Pattern pattern = Pattern.compile(".*faultString([^\\n]*).*", Pattern.DOTALL);
      

      【讨论】:

        【解决方案6】:

        请记住,正则表达式的东西很昂贵。 Chetan 的想法是对的。

        这是一些示例代码--

            String errorString = "AxisFault\n"
                    + "          faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException\n"
                    + "          faultSubcode: \n" 
                    + "          faultString: My Error\n"
                    + "          faultActor: \n" 
                    + "          faultNode: \n"
                    + "          faultDetail: \n"
                    + "                 {}string: this is the fault detail";
        
            Properties p = new Properties();
            ByteArrayInputStream bis = new ByteArrayInputStream(errorString
                    .getBytes());
        
            try {
                p.load(bis);
            } catch (IOException e) {
        
            }
        
            System.out.println(p.toString());
            System.out.println(p.getProperty("faultString"));
        

        【讨论】:

        • 我不认为属性处理除“=”之外的分隔符。当然,自定义解析器可能会更快,但通常不需要过多担心错误报告的性能。
        【解决方案7】:

        也许是getFaultString? :)

        编辑:或 ((AxisFault) exception.getRootCause()).getFaultString()。我只是认为您可能忽略了一个事实,即您可以直接从 AxisFault 本身获取它。

        【讨论】:

        • 我要拉几个字段。
        • 实际上,在仔细研究 AxisFault 之后,您的方法更有意义。正则表达式过于工程化。仍然是一个很好的练习来弄乱 reg ex 的东西。
        猜你喜欢
        • 1970-01-01
        • 2015-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-02
        相关资源
        最近更新 更多