正则表达式是程序员的强大工具,但是-在某些情况下,它们不是最佳选择,甚至是完全有害的。
简单的示例1是使用regexp解析HTML-已知的众多错误之路。通常,这也可能归因于解析。
但是,还有其他显然不能使用正则表达式的区域吗?
ps:“ 您要提出的问题似乎是主观的,很可能已经解决。 ”-因此,我想强调一点,就是我对使用正则表达式会导致问题的示例感兴趣。
正则表达式是程序员的强大工具,但是-在某些情况下,它们不是最佳选择,甚至是完全有害的。
简单的示例1是使用regexp解析HTML-已知的众多错误之路。通常,这也可能归因于解析。
但是,还有其他显然不能使用正则表达式的区域吗?
ps:“ 您要提出的问题似乎是主观的,很可能已经解决。 ”-因此,我想强调一点,就是我对使用正则表达式会导致问题的示例感兴趣。
Answers:
不要使用正则表达式:
这不限于HTML。即使知道模式并且知道它永远不会改变,也不能使用正则表达式合理地解析简单的有效XML。
例如,不要尝试解析C#源代码。相反,解析它以获得有意义的树结构或令牌。
如果必须搜索大小写的字母怎么办?如果您喜欢正则表达式,则可以使用它们。但是使用两个搜索,一个接一个地搜索是否更容易/更快/更容易阅读?在大多数语言中,您都有可能获得更好的性能,并使代码更具可读性。
例如,当您不能使用正则表达式时,Ingo答案中的示例代码就是一个很好的例子。只是搜索foo
,然后搜索bar
。
淫秽过滤器就是一个很好的例子。通常,实现它不仅是一个坏主意,而且您可能会想使用正则表达式来实现它,但是这样做会出错。一个人可以通过多种方式写一个单词,一个数字,一个句子,并且另一个人可以理解它,但是您的正则表达式却不行。因此,您的正则表达式不会花费很多时间来伤害其他用户,而不是使您感到淫秽。
例如,不要通过正则表达式来验证电子邮件地址。在大多数情况下,您会做错事情。在极少数情况下,您会做对并以6 343个字符长的编码恐怖结束。
没有正确的工具,您会犯错误。您会在最后一刻注意到它们,或者可能永远不会注意到它们。如果您不关心干净的代码,则将编写二十行的字符串,其中不包含注释,空格和换行符。
认真地说,如果我接受您的代码并必须对其进行检查或修改,那么我不想花一个星期的时间来理解长达20行的字符串,其中包含许多符号。
(?(DEFINE))
断言的;)您可以使用它们编写非常干净的regexe,实际上,当您使用它们时,您将编写语法非常类似于您用yacc等编写的内容;)
"<a href='foo'>stuff</a>"
。现代正则表达式对此没有任何问题。
最重要的是:当您解析的语言不是常规语言时。
HTML是不是一个正规的语言,并用正则表达式解析它是没有可能的(不仅难以或道路bug的代码)。
在stackoverflow上经常会看到人们要求使用正则表达式来查找给定的字符串是否不包含该字符串。恕我直言,这颠倒了正则表达式的目的。即使存在解决方案(采用断言在后面的断言或类似的东西),通常也最好使用正则表达式进行处理,并使用程序逻辑处理否定情况。
例:
# bad
if (/complicated regex that assures the string does NOT conatin foo|bar/) {
# do something
}
# appropriate
if (/foo|bar/) {
# error handling
} else {
# do something
}
两种情况:
大多数语言都提供了一个简单的函数,如INSTR,来确定一个字符串是否是另一个字符串的子集。如果您要这样做,请使用更简单的功能。不要写自己的正则表达式。
如果有一个库可以执行复杂的字符串操作,请使用它,而不要编写您自己的正则表达式。
正则表达式无法识别递归结构。这是基本限制。
以JSON-这是一种非常简单的格式,但是由于一个对象可能包含其他对象作为成员值(任意深),因此语法是递归的,并且不能由正则表达式解析。另一方面,由于CSV 不包含任何递归结构,因此可以通过正则表达式进行解析。
简而言之,正则表达式不允许模式引用自身。您不能说:此时语法再次匹配整个模式。换句话说,正则表达式仅线性匹配,它不包含堆栈,因此它无法跟踪嵌套模式的深度。
请注意,它与格式的复杂程度或复杂程度无关。S表达式确实非常简单,但是不能用正则表达式解析。另一方面,CSS2是一种相当复杂的语言,但是不包含递归结构,因此可以使用正则表达式进行解析。(尽管由于CSS表达式具有递归语法,所以CSS3并非如此。)
这样做不是因为仅使用正则表达式来解析HTML是丑陋,复杂或容易出错的。这是根本不可能的。
如果您需要解析包含递归结构的格式,则至少需要使用正则表达式来补充堆栈,以跟踪递归结构的级别。这通常是解析器的工作方式。正则表达式用于识别“线性”部分,而正则表达式外的自定义代码用于跟踪嵌套结构。
通常,像这样进行解析会分为多个阶段。令牌化是使用正则表达式将输入拆分为一系列“令牌”(如单词,标点,方括号等)的第一阶段。解析是下一阶段,其中将这些令牌解析为层次结构(语法树)。
因此,当您听到HTML或C#无法由正则表达式解析时,请注意,正则表达式仍然是解析器的关键部分。您只是不能仅使用正则表达式而不使用辅助代码来解析此类语言。