正则表达式 字符串解析

Dan*_*Dan 33 regex language-agnostic string performance parsing

有可能打开一堆蠕虫并获得负面投票,我发现自己需要问,

我什么时候应该使用正则表达式?何时更适合使用字符串解析?

而且我将需要关于你的立场的例子推理.我希望你能解决一些问题,比如可读性,可维护性,扩展性以及你答案中最重要的性能.

我发现另一个问题在这里只有一个答案,甚至困扰一个例子.我需要更多了解这一点.

我目前正在使用C++,但是正则表达式几乎都是高级语言,我想知道不同的语言如何使用/处理正则表达式,但这更像是一种思考.

感谢您帮助理解它!

编辑:我仍然在寻找更多的例子,并就此进行讨论,但到目前为止的反应非常好.:)

Mik*_*uel 31

这取决于你所处理的语言有多复杂.

拆分

它很有用,但只有在没有转义约定时才有效.例如,它不适用于CSV,因为引用字符串中的逗号不是正确的分割点.

FOO,酒吧,巴兹

可以拆分,但是

FOO, "酒吧,巴兹"

不能.

定期

正则表达式非常适合具有"常规语法"的简单语言.由于反向引用,Perl 5正则表达式更强大,但一般的经验法则是:

如果需要匹配括号((...),[...])或其他嵌套(如HTML标记),那么正则表达式本身是不够的.

您可以使用正则表达式将字符串分解为已知数量的块 - 例如,从日期中拉出月/日/年.虽然它们是解析复杂算术表达式的错误工作.

显然,如果你写一个正则表达式,走开去喝杯咖啡,回来,并且不能轻易理解你刚写的东西,那么你应该寻找一种更清晰的方式来表达你正在做的事情. 电子邮件地址可能是使用正则表达式正确和可读地处理的限制.

无上下文

解析器生成器和手动编码的下推/ PEG解析器非常适合处理需要处理嵌套的更复杂的输入,因此您可以构建或处理运算符优先级或关联性.

无上下文解析器通常使用正则表达式首先将输入分解为块(空格,标识符,标点符号,引用字符串),然后使用语法将该块流转换为树形式.

CF语法的经验法则是

如果正则表达式不足,但语言中的所有单词都具有相同的含义,无论先前的声明如何,那么CF都可以工作.

非上下文免费

如果您的语言中的单词根据上下文改变含义,那么您需要一个更复杂的解决方案.这几乎总是手工编码的解决方案.

例如,在C中,

#ifdef X
  typedef int foo
#endif

foo * bar
Run Code Online (Sandbox Code Playgroud)

如果foo是一个类型,那么foo * bar是一个foo名为的指针的声明bar.否则它是foo由名为变量命名的变量的乘法bar.

  • @Dan,正则表达式可以很好地处理CSV文件 - 没有任意深度嵌套,只有两层深度结构.对于IE样式,您可以使用类似`/([^\r \n"] |"(?:[^"] |"")*")/ g`的内容找到这些行,它允许在引用的字符串中使用换行符成对的双引号来转义双引号.然后你可以使用类似`/([^,"] |"(?:[^"] |"")*")*/g`的东西找到一行中的字段.然后你只需要找到引用的部分使用/"(?:[^"] |"")*"/,外部引号的条带,并用`"`替换所有出现的````. (3认同)

Ani*_*dha 8

它应该是正则表达式和字符串解析 ..

您可以使用它们两个优势!很多时候程序员尝试制作一个SINGLE正则表达式来解析文本然后发现它很难维护.您应该在需要时使用它们.

REGEX引擎是快速的.简单匹配只需不到一微秒.但不推荐用于解析HTML.

  • `你应该在必要时使用它们.什么时候?我需要一个例子.我的意思是你所说的有道理,但我需要解释你究竟是什么意思. (3认同)
  • @Dan,看看我对一个常见案例的回答.在解析CF语言时,通常使用正则表达式将其拆分为标记,然后使用完整的解析器处理该标记流.例如,你可以将`"(a + b)*c"`分解为`["(","","a","+","","b",")","*", "c"]`然后抛出空格并将结果提供给解析器来处理括号和运算符优先级以生成类似`(Times(Plus(Var"a")(Var"b"))的树(Var) "C"))`. (2认同)