何时值得在Java中使用RegEx?

时间:2010-11-08 15:44:26

标签: java regex

我正在编写一个小应用程序,它会读取一些输入并根据该输入执行某些操作。

目前我正在寻找以“魔术”结尾的行,我会使用String的endsWith方法。对于那些正在阅读我的代码的人来说,这是非常清楚的。

另一种方法是创建一个Pattern并尝试匹配以“magic”结尾的行。这一点也很清楚,但我个人认为这是一种矫枉过正,因为我所寻找的模式并不复杂。

您认为何时使用RegEx Java值得?如果它的复杂性,你将如何个人定义什么是复杂的?

此外,是否有时候使用模式实际上比字符串操作更快?

编辑:我正在使用Java 6。

11 个答案:

答案 0 :(得分:10)

基本上:如果有一个非正则表达式操作可以在一个步骤中执行您想要的操作,请始终执行此操作。

这不是关于性能,而是关于a)可读性和b)编译时安全性。专用的非正则表达式版本通常比正则表达式版本更容易阅读。并且其中一个专门方法中的拼写错误将无法编译,而正则表达式中的拼写错误将在运行时失败。

将基于正则表达式的解决方案与非正则表达式解决方案进行比较

String s = "Magic_Carpet_Ride";

s.startsWith("Magic");   // non-regex
s.matches("Magic.*");    // regex

s.contains("Carpet");    // non-regex
s.matches(".*Carpet.*"); // regex

s.endsWith("Ride");      // non-regex
s.matches(".*Ride");     // regex

在所有这些情况下,这是一个明智的选择:使用非正则表达式版本。

但是当事情变得更复杂时,这取决于。我想在以下情况下我仍然坚持使用非正则表达式,但很多人不会:

// Test whether a string ends with "magic" in any case,
// followed by optional white space
s.toLowerCase().trim().endsWith("magic"); // non-regex, 3 calls
s.matches(".*(?i:magic)\\s*");            // regex, 1 call, but ugly

回应RegexesCanCertainlyBeEasierToReadThanMultipleFunctionCallsToDoTheSameThing

我仍然认为非正则表达式版本更具可读性,但我会这样写:

s.toLowerCase()
 .trim()
 .endsWith("magic");

完全不同,不是吗?

答案 1 :(得分:3)

当对String类的正常操作不足以从String中优雅地获得所需内容时,您将使用Regex。

这是一个很好的指标,当你开始分裂,然后分割这些结果,然后分割这些结果。代码变得笨拙。两行Pattern / Regex代码可以清理它,整齐地包裹在一个经过单元测试的方法中....

答案 2 :(得分:2)

任何可以使用正则表达式完成的操作也可以手工编码。

使用正则表达式:

  1. 手动操作会花费更多精力而没有太多好处。
  2. 您可以轻松地为您的任务提出正则表达式。
  3. 使用正则表达式:

    1. 这样做非常容易,就像你的例子一样。
    2. 您正在解析的字符串不适合正则表达式。 (习惯上链接到this question

答案 3 :(得分:1)

我认为您最好使用endsWith。除非您的要求发生变化,否则更简单易懂。也可以更快地执行。

如果有更多的复杂性,例如你想匹配“魔法”,“majik”,但不是“魔法”或“Majik”;或者你想匹配“魔法”后跟一个空格然后1诸如“......魔术勺”之类的词,而不是“......魔术汤匙”,那么我认为RegEx将是一个更好的方式。

答案 4 :(得分:0)

当您考虑计算能力和为此目的生成代码所需的智能时,使用RegEx可以更好地完成生成大量对象的任何复杂解析。如果你有一个方便的RegEx专家,它几乎总是值得的,因为模式可以很容易地调整,以适应业务规则的变化,而无需重大的循环重构,如果你使用纯java来做一些RegEx所做的复杂事情,可能需要这样做。 / p>

答案 5 :(得分:0)

有一种说法:

有些人在面对问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。 (link)。

对于一个简单的测试,我会像你一样完成。如果你发现它变得越来越复杂,那么只有在没有其他方法时才会考虑正则表达式。

答案 6 :(得分:0)

如果您的基本行结尾每次都相同,例如“magic”,那么您最好使用endsWith。

但是,如果您的行具有相同的基础,但可以具有多个值,例如:

<string> <number> <string> <string> <number>

字符串和数字可以是任何东西,你最好使用RegEx。

您的行总是以字符串结尾,但您不知道该字符串是什么。

答案 7 :(得分:0)

如果它像endsWith,startsWith或contains一样简单,那么你应该使用这些函数。如果您正在处理更多“复杂”字符串并且想要从这些字符串中提取信息,则可以使用regexp / matchers。

如果您有类似“commandToRetrieve someNumericArgs someStringArgs someOptionalArgs”的内容,那么regexp将大大减轻您的任务:)

答案 8 :(得分:0)

如果我有更简单的方法,我永远不会在java中使用正则表达式,例如endsWith方法。 java中的正则表达式一样丑陋,可能除了matchString方法的唯一例外。

通常避免使用正则表达式可以让您的核心对其他程序员更具可读性和易用性。反之亦然,复杂的正则表达式甚至可能会让那些经验最丰富的黑客感到困惑。

至于性能问题:只是简介。特别是在java。

答案 9 :(得分:0)

当您知道输入的格式但我不一定确定格式化输入的(或可能的值)时,我建议使用正则表达式。

我在说什么,如果你的输入全部以“魔术”结尾,那么String.endsWith()工作正常(看到你知道你的可能输入值将以“魔法”结束)。

如果您的格式为RFC 5322 message format,则无法清楚地说明所有电子邮件地址都以.com结尾,因此您可以创建符合RFC 5322标准的正则表达式进行验证

简而言之,如果您知道输入数据的格式结构但不确切知道可以接收的值(或可能的值),请使用正则表达式进行验证。

答案 10 :(得分:0)

如果您熟悉正则表达式的工作方式,您很快就会发现使用正则表达式可以轻松解决许多问题。

就个人而言,如果这很容易,我会考虑使用java String操作,但如果你开始拆分字符串并再次对它们进行子串,我会开始考虑使用正则表达式。

而且,如果你使用正则表达式,为什么要停在线上。通过配置正则表达式,您可以轻松地在一个正则表达式中读取整个文件(Pattern.DOTALL作为Pattern.compile的参数,并且您的正则表达式不会在换行符中结束)。我将它与Apache Commons IOUtils.toString()方法结合起来,你可以使用非常强大的功能来快速完成任务。

如果需要,我甚至会带出一个正则表达式来解析一些xml。 (例如,在单元测试中,我想检查xml中是否存在某些元素。)

例如,从我的一些单元测试:

Pattern pattern = Pattern.compile(
                "<Monitor caption=\"(.+?)\".*?category=\"(.+?)\".*?>"
                + ".*?<Summary.*?>.+?</Summary>"
                + ".*?<Configuration.*?>(.+?)</Configuration>"
                + ".*?<CfgData.*?>(.+?)</CfgData>", Pattern.DOTALL);

将匹配此xml中的所有段,并选择一些我想要进行子匹配的段。