什么时候最好使用正则表达式而不是基本的字符串拆分/子串?

时间:2008-12-10 22:21:35

标签: regex parsing string

似乎使用字符串解析与正则表达式的选择会在我出现需要部分字符串,有关所述字符串的信息等的情况下随时出现。

出现这种情况的原因是我们正在评估一个soap标头的动作,之后它已被解析为可通过WCF的OperationContext对象和然后管理的东西。做出决定。现在,简单的解决方案似乎是基本的子串,以保持实现简单,但我的一部分想知道RegEx是否更好或更强大。我的另一部分想知道在我们的特定场景中是否使用霰弹枪来杀死苍蝇。

所以我不得不问,在尝试决定使用RegEx而不是典型的字符串解析时,人们使用的典型阈值是多少。请注意,我在正则表达式方面不是很强,因此,我试图回避,除非避免引入比我需要的更多复杂性至关重要。

如果您无法通过我选择的缩写来判断,这是在.NET版本(C#)中,但我认为这与此问题没有多大关系。


编辑:根据我典型的Raybell魅力,我在问题中过于冗长或误导。我想道歉。我提供了一些背景知识,以帮助提供关于我在做什么的线索,而不是误导人。

我基本上在寻找关于何时使用子字符串及其变体的指南,而不是正则表达式,反之亦然。虽然有些答案可能已经错过了这一点(我的错也是如此),但我真的很感激他们并且相应地进行了投票。

7 个答案:

答案 0 :(得分:22)

我的主要指导是使用正则表达式来提供一次性代码和用户输入验证。或者当我试图在大量文本中找到特定模式时。对于大多数其他目的,我将编写一个语法并实现一个简单的解析器。

一个重要的指导原则(虽然我看到人们一直在尝试,但是很难回避)是在目标语言的语法是递归的情况下总是使用解析器。

例如,考虑一种微小的“表达式语言”来评估括号中的算术表达式。这种语言的“程序”示例如下:

1 + 2
5 * (10 - 6)
((1 + 1) / (2 + 2)) / 3

语法很容易编写,看起来像这样:

DIGIT := ["0"-"9"]
NUMBER := (DIGIT)+
OPERATOR := ("+" | "-" | "*" | "/" )
EXPRESSION := (NUMBER | GROUP) (OPERATOR EXPRESSION)?
GROUP := "(" EXPRESSION ")"

使用该语法,您可以在jiffy中构建递归下降解析器。

等效的正则表达式 REALLY 难以编写,因为正则表达式通常不能很好地支持递归。

另一个很好的例子是JSON摄取。我见过人们尝试使用正则表达式来使用JSON,而且它是INSANE。 JSON对象是递归的,所以它们只是求助于常规语法和递归下降解析器。


嗯......看看其他人的回答,我想我可能回答错了。

我把它解释为“什么时候应该使用简单的正则表达式,而不是一个完整的解析器?”而大多数人似乎都把这个问题解释为“你应该何时推出自己的笨拙的逐个字符验证方案,而不是使用正则表达式?”

鉴于这种解释,我的答案是:永远不会。


好的......还有一个编辑。

我会对你自己的计划更加宽容。只是......不要称它为“解析”:o)

我认为一个好的经验法则是,如果您可以使用单个谓词实现所有逻辑,则应该只使用字符串匹配原语。像这样:

if (str.equals("DooWahDiddy")) // No problemo.

if (str.contains("destroy the earth")) // Okay.

if (str.indexOf(";") < str.length / 2) // Not bad.

一旦你的条件包含多个谓词,那么你就已经开始发明自己的特殊字符串验证语言,你可能应该只是编写一些正则表达式。

if (str.startsWith("I") && str.endsWith("Widget") &&
    (!str.contains("Monkey") || !str.contains("Pox")))  // Madness.

正则表达式真的不难学。与具有数十个关键字,原始类型和运算符的C#等huuuuge全功能语言以及具有数千个类的标准库相比,正则表达式绝对简单。大多数正则表达式实现支持大约十几个操作(给予或接受)。

这是一个很好的参考:

http://www.regular-expressions.info/

PS:作为奖励,如果你想要学习编写自己的解析器(使用lex / yacc,ANTLR,JavaCC或其他类似工具),学习正则表达式是一个很好的准备,因为解析器 - 生成器工具使用许多相同的原则。

答案 1 :(得分:6)

正则表达式可以是

  • 更容易理解
  • 更清楚地表达意图
  • 短得多
  • 更容易改变/适应

在某些情况下,所有这些优点都可以通过使用正则表达式实现,而在其他情况下只实现了一些(例如,正则表达式并不是很容易理解),而在其他情况下,正则表达式更难理解,混淆了意图,更长,更难改变。

我从正则表达式获得的那些(可能还有其他)优势越多,我就越有可能使用它们。

可能的经验法则:如果理解正则表达式对于熟悉正则表达式的人需要几分钟,那么你不想使用它(除非“正常”代码更复杂; - )。 / p>

嗯...仍然没有简单的经验法则,抱歉。

答案 2 :(得分:2)

  

[W]正在评估一个肥皂头   采取行动并做出决定

永远不要使用正则表达式或基本字符串解析来处理XML。现在常用的每种语言都有完美的XML支持。 XML是一个看似复杂的标准,你的代码不太可能正确地解析所有格式良好的XML输入,即使它是,你也浪费你的时间,因为(正如刚才提到的)每一种语言都是常见用法有XML支持。使用正则表达式解析XML是不专业的。

要回答您的问题,一般来说,正则表达式的使用应该最小化,因为它们不是非常易读。通常,您可以组合字符串解析和正则表达式(可能在循环中)来创建比单独的正则表达式更简单的解决方案。

答案 3 :(得分:1)

当您所需的转换不是基本的 - 但在概念上仍然很简单。

如果你正在进行直接的字符串替换,

没有理由拔出正则表达式,例如...它更容易使用string.Replace

另一方面,如果你没有明确地写出来,一个包含许多条件或特殊情况的复杂规则将需要超过50个字符的正则表达式,这可能是一个噩梦。

答案 4 :(得分:1)

我同意benjismith的说法,但是想稍微详细说明一下。对于非常简单的语法,基本的字符串解析可以很好地工作,但正则表达式也可以。我不会称他们矫枉过正。如果它工作,它的工作原理 - 与你发现的最简单。对于中等到中间的字符串解析,通常采用正则表达式。

一旦你开始发现自己需要定义一个语法,即复杂的字符串解析,尽可能快地回到使用某种有限状态机或类似的东西。正则表达式不能很好地扩展,使用松散的术语。它们变得复杂,难以解释,甚至无能为力。

我至少看到过一个项目,其中正则表达式的使用不断增长和增长,很快他们就无法插入新功能。当它最终有时间做一个新的主要版本时,他们会抛弃所有的正则表达式并走上语法分析器的路径。

答案 5 :(得分:0)

我认为最简单的方法是知道何时使用正则表达式,何时不使用,当你的字符串搜索需要IF / THEN语句或任何类似于这个或那个逻辑的东西时,你需要比简单字符串比较更好的东西这是正则表达式闪耀的地方。

答案 6 :(得分:0)

我总是使用正则表达式,除非它是非常简单的东西,比如拆分逗号分隔的字符串。如果我认为有一天弦乐有可能变得更复杂,我可能会从正则表达式开始。

我不认同正则表达式很难或很复杂的观点。这是每个开发人员应该学习和学习的一个工具。它们有无数的用途,一旦学会了,这就是你再也不用担心的事情了。

正则表达式很少是矫枉过正 - 如果匹配很简单,那么正则表达式也是如此。