为什么正则表达式这么有争议?[关闭]


212

在探索正则表达式(也称为RegEx-es)时,似乎有很多人将正则表达式视为圣杯。看起来如此复杂的东西-仅仅是任何问题的答案。他们倾向于认为使用正则表达式可以解决每个问题。

另一方面,也有许多人试图不惜一切代价避免使用正则表达式。他们试图找到一种围绕正则表达式的方法,并仅出于此目的接受其他编码,即使正则表达式将是一个更紧凑的解决方案。

为什么正则表达式这么有争议?关于它们的工作原理是否存在广泛的误解?还是可以广泛相信正则表达式通常很慢?


9
如果这是一个讨论,那么不应该关闭吗?但是我在那里看到一个真正的问题,所以也许讨论标签不属于?
RCIX

6
别开玩笑了。提起它,周围的人开始变得疯狂。
Ryan Florence

1
很好的观察和措辞的问题!
imz-伊万·扎哈拉里谢夫(Ivan Zakharyaschev)2011年


问题是基于意见的规则也应在此处应用(或应编辑问题以针对准确的答案)。这就是说,我认为正则表达式的争议源于对它的教程和手册的不精确。在大多数情况下,如果不是所有时间的信息都混合在一起,而且我们没有得到所有特征。除了使用该语言外,您最终还会学到一些东西,以备不时之需。最后,特殊的正则表达式字符不仅限于一种会增加混乱的含义。
intika

Answers:


136

我不认为人们反对正则表达式是因为它们很慢,而是因为它们很难读写,而且很难正确。尽管在某些情况下正则表达式可以为问题提供有效,紧凑的解决方案,但有时它们会纠缠于最好使用易于阅读且可维护的代码部分的情况。


2
是的,与使用简单函数相比,正则表达式可能非常慢。不仅速度很慢,而且面对任意(用户提供的)输入时,正则表达式引擎的性能可能完全不可预测
Pacerier,2015年

1
如果您知道正则表达式是如何工作的,那根本不是问题。
Shiplu Mokaddim

8
@pacerier,这不是慢速模式,而是慢速引擎。大多数(现代)正则表达式引擎不适合复杂的模式(例如,许多|.*),因为它们使用堆栈机并回溯。这就是为什么您必须在Perl,Java,Python,Ruby中仔细调整正则表达式的原因。老式的正则表达式引擎(grep例如在中)首先将模式编译为DFA。此后,模式的复杂性在很大程度上是无关紧要的。我只是使用Java和grep来表示相同的文本和模式:22min vs 2s。这是科学所在:swtch.com/~rsc/regexp/regexp1.html
hagello

122

使正则表达式可维护

揭开先前称为“正则表达式”的模式的神秘面纱的主要进步是Perl的 /x regex标志(有时是(?x)在嵌入时编写的)可以空格(换行,缩进)和注释,这。这严重提高了可读性,从而提高了可维护性。空白允许进行认知分块,因此您可以看到哪些组与哪些组。

现在,现代模式现在也支持相对编号和命名的反向引用。这意味着您不再需要计算捕获组来确定您需要$4还是\7。这在创建可以包含在其他模式中的模式时会有所帮助。

这是一个相对编号的捕获组的示例:

$ dupword = qr {\ b(?:(\ w +)(?:\ s + \ g {-1})+)\ b} xi;
$ quoted = qr {([“'])$ dupword \ 1} x;

这是命名捕获的高级方法的示例:

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

语法正则表达式

最好的是,可以将这些命名捕获放置在一个(?(DEFINE)...)块中,以便您可以将声明与执行模式的各个命名元素分开。这使它们的行为类似于模式中的子例程。
这种“语法正则表达式”的一个很好的例子可以在这个答案这个答案中找到。这些看起来更像是一个语法声明。

正如后者提醒您的那样:

…确保永远不要写线噪声模式。您不必也不应该。禁止保留空格,注释,子例程或字母数字标识符的任何编程语言都无法维护。因此,请在模式中使用所有这些内容。

这不能过分强调。当然,如果您不在模式中使用这些内容,则通常会造成一场噩梦。但是,如果您确实使用它们,则不需要。

这是现代语法模式的另一个示例,该示例用于解析RFC 5322:使用5.10.0;

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

那不是很了不起-很棒吗?您可以采用BNF风格的语法并将其直接转换为代码,而不会丢失其基本结构!

如果现代语法模式仍然不能满足您的需求,那么Damian Conway出色的Regexp::Grammars模块将提供更加简洁的语法,并提供出色的调试功能。这是用于将RFC 5322重铸为该模块的模式的相同代码:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

有很多的好东西perlre手册页,但在基本的正则表达式的设计特点,这些显着改善绝不单单局限于Perl的手段。实际上pcrepattern联机帮助页可能更容易阅读,并且涵盖了相同的领域。

现代模式与您在有限自动机课程中教过的原始事物几乎没有共通之处。


9
是!是!最后,有人展示了一个很好的例子,说明了使用x修饰符可读取的正则表达式如何。我不敢相信有多少人知道它的存在,更不用说实际使用它了。
Shabbyrobe

1
@Shabbyrobe:不只是/x。它在语法上使用了(?&name)正则表达式以及内部正则表达式子例程,这确实使它大放异彩。
tchrist

+1您总是学到新东西。我不知道PCRE对于定义具有“假”条件。
NikiC 2011年

5
Python同样具有一个re.VERBOSE标志。
机械蜗牛

3
刚纳(Gunna)继续说,我仍然对人们为了使正则表达式可用而付出的努力感到惊讶。
Slater Victoroff 2015年

68

正则表达式是一个很棒的工具,但是人们认为“嘿,多么伟大的工具,我将用它来做X!” X是其他工具更适合的东西(通常是解析器)。这是在需要螺丝刀问题时使用锤子的标准配置。


4
请记住,大多数解析器-词法分析器-仍使用正则表达式来解析它们的内容:-)
Jasper Bekkers 2009年

62
说解析器使用正则表达式就像说解析器使用赋值语句。除非您查看如何使用它们,否则它什么都没有。
Chas。欧文斯(Owens)2009年

24
在解析器更好的情况下使用RegEx很烦人。当该语言的标准字符串查找或替换功能将正常工作(通常在线性时间内)时,使用RegEx就是不可原谅的。
jmucchiello

1
同意,因为RegEx必须成为所有交易的重心,所以它的处理开销非常大。仅仅因为使用RegEx引擎看起来容易,并不意味着它比迭代解析器(与开发人员相关的阈值)更好。我最喜欢的示例之一是PHP的split($pattern,$string)vs- explode($delimiter,$string)值得庆幸的是,前者已贬值,但是许多代码只在需要后者功能的情况下才使用前者。Aggreed,RegEx提供了一种简单的工具来执行某些操作,但是除非您需要正则表达式的全部功能,否则它们
Rudu 2010年

4
词法分析器确实可以使用正则表达式。它们也称为标记器,但不是语法分析器(或解析器)。要读取足够复杂的字符串,应使用标记程序将字符串作为标记读取(也许使用正则表达式,也许不,取决于标记程序)。然后将这些令牌传递给解析器,解析器将使用语法规则(绝对不是正则表达式)处理它们。
Axel

53

我认识的几乎每个定期使用正则表达式(意在双关语)的人都来自Unix-ish背景,他们使用将RE视为一流编程结构的工具,例如grep,sed,awk和Perl。由于使用正则表达式几乎没有语法上的开销,因此使用正则表达式时,它们的生产力会大大提高。

相反,使用RE作为外部库的语言的程序员往往不考虑正则表达式可以带给表什么。程序员的“时间成本”非常高,以至于a)RE从未作为培训的一部分出现,或者b)他们不对RE进行“思考”,而是倾向于使用更熟悉的模式。


11
是的,我从不原谅Python使用库使regex语法冗长。我认为这是纯洁而非理智。
slikts

7
我来自Unix背景,使用过sed,awk和perl加载,当然也做了很多grepping,但是我知道当我使用正则表达式时,这是我讨厌维护的只写黑客。这对于s​​hell脚本/一次性脚本非常有用,但是对于实际工作而言,对于不只是立即保存某些数据的任何事情,我现在使用具有清晰语法的适当的tokenizer / lexer / parser。我最喜欢做的全部/任何事情都可以+自我优化。我已经学会了艰辛的方法,并且多年来,开始时有一点自律就意味着以后的工作更少。正则表达式是键盘上的一刻,皱着眉头是一生。
AndrewC 2012年

44

正则表达式允许您以紧凑的方式编写自定义有限状态机(FSM),以处理输入字符串。很难使用正则表达式的原因至少有两个:

  • 老式软件开发涉及许多计划,论文模型和仔细的思考。正则表达式非常适合此模型,因为正确编写有效的表达式会涉及很多盯着它,并可视化FSM的路径。

    现代软件开发人员宁愿敲定代码,而是使用调试器逐步执行,以查看代码是否正确。正则表达式不能很好地支持这种工作方式。正则表达式的一个“运行”实际上是一种原子操作。很难在调试器中观察到逐步执行。

  • 编写一个正则表达式,意外地接受了比您预期更多的输入,这太容易了。正则表达式的值并不是真正匹配有效输入,而是不能匹配无效输入。对正则表达式执行“负测试”的技术不是很先进,或者至少没有广泛使用。

    正则表达式难以理解。仅通过查看正则表达式,就需要花费大量精力来可视化应拒绝但被错误接受的所有可能的输入。是否曾经尝试调试别人的正则表达式代码?

如果今天在软件开发人员中反对使用正则表达式,我认为主要是由于这两个因素。


4
有出色的工具可以调试regexp
Jasper Bekkers,2009年

15
perl -Mre = debug -e“ q [aabbcc] =〜/ ab * [cd] /”
Brad Gilbert

15
我想我从来没有想到过飞行意大利面条怪物这个缩写词“ FSM”。
Shabbyrobe

4
@Shabbyrobe:我不是要冒犯。如果需要,可以使用确定性有限自动机(DFA)。
Bill Karwin

37

人们倾向于认为正则表达式很困难。但这是因为他们错误地使用了它们。编写复杂的单行代码,不加任何评论,缩进或命名捕获。(您不会在没有注释,缩进或别名的情况下一行就塞满复杂的SQL表达式,对吗?)。所以是的,对于很多人来说,他们没有道理。

但是,如果你的工作有什么做解析文本(大致任何Web应用程序在那里......),你不知道正则表达式,你吮吸你的工作,你是在浪费自己的时间和你的雇主。那里有出色的资源可以教您所有您需要知道的所有知识,以及更多。


2
嗯..不同之处在于,多个空格在正则表达式中具有含义,而在其他语言中则没有,这就是为什么它们通常是一个衬里(有时会换成多行:)的原因
Rado

14
@Rado:例如,Perl具有正则x表达式的修饰符,导致空白被忽略。这使您可以将正则表达式放在几行上并添加注释。
内森·费尔曼

9
同样Python有re.X又名re.VERBOSE
Craig McQueen 2010年

2
同样x,tcl中的修饰符。我相信这是相当标准的,因为tcl与其他语言不同,它不使用PCRE。
slebetman

2
@AndrewC这是这篇文章可能引起的最严重的误解之一。
Jasper Bekkers

28

因为它们缺乏通用的IDE中最流行的学习工具,所以没有Regex向导。甚至没有自动完成功能。您必须自己编写整个代码。


3
那么您使用的是错误的IDE。甚至我的文本编辑器也提供了正则表达式提示。
CurtainDog

1
另外,Expresso和Regex Coach是用于构造正则表达式的非常有用的工具。

22
您将如何自动完成正则表达式?
2009年

3
EditPad Pro在搜索框中具有针对正则表达式的语法突出显示功能,但我发现它比有用的功能更烦人,并且保持关闭状态。但是我很感激当我拥有无与伦比的括号时让我知道。括号尤其可以作为追踪对象。
艾伦·摩尔

2
@AmbroseChapel-我距离这次讨论晚了几年。但是我在regexhero.net/tester上创建了一个自动补全机制, 该机制是由圆括号(),方括号[]或大{}括号内的常见构造启动的。反斜杠也可以使用。
史蒂夫·沃瑟姆


16

我认为他们没有那么大的争议。

我还认为您已经回答了自己的问题,因为您指出了在任何地方使用它们(并非所有内容都是常规语言 2)或完全避免使用它们多么愚蠢。您(程序员)必须对正则表达式何时对代码有所帮助或不利做出明智的决定。面对这样的决定时,要牢记的两个重要事项是可维护性(这意味着可读性)和可扩展性。

对于那些特别讨厌他们的人,我猜他们从来没有学会正确使用它们。我认为大多数只花几个小时学习一个体面的教程的人都会发现它们并很快变得流利。这是我从哪里开始的建议:

http://docs.python.org/howto/regex

尽管该页面讨论了Python上下文中的正则表达式,但我发现该信息在其他地方也非常适用。有一些特定于Python的东西,但是我相信它们已经清楚地指出并且易于记忆。


2
该页面似乎已移至docs.python.org/howto/regex
Dominic K

@DMan谢谢。我将编辑答案以反映出来。
allyourcode

11

正则表达式是字符串,而算术运算符是数字,我不会认为它们有争议。我认为,即使像我这样的相当善良的OO活动家(他们倾向于在字符串上选择其他对象)也将很难被拒绝。


7

问题在于正则表达式可能功能强大,以至于您可以使用正则表达式执行某些操作,因此应使用其他功能。

一个好的程序员应该知道在哪里使用它们,而不是在哪里使用。典型示例是解析非常规语言(请参阅确定语言是否为常规语言)。

我认为,如果您一开始将自己限制为真正的正则表达式(无扩展名),那么您不会出错。某些扩展可以使您的生活更轻松一些,但是,如果您发现很难将其表达为真正的正则表达式,则很可能表明正则表达式不是正确的工具。


5

您几乎还可能会问为什么goto会引起争议。

基本上,当您获得如此多的“显而易见”的力量时,人们往往会在并非最佳选择的情况下滥用它们。例如,要求解析正则表达式中的CSV或XML或HTML的人数令我震惊。这是工作的错误工具。但是有些用户仍然坚持使用正则表达式。

就我个人而言,我尝试找到一种快乐的媒介-使用正则表达式来实现它们的优势,并在它们不是最佳选择时避免使用它们。

请注意,正则表达式仍可用于解析CSV,XML,HTML等。但通常不能在单个正则表达式中使用。


当然,您可以在单个正则表达式中解析任何一种格式,这就是正则表达式的力量,宝贝!是否要这样做完全是另一回事。
贾斯珀(Jasper)2010年

4

我认为“有争议”是正确的词。

但是我看到了无数的例子,人们说“进行这样的字符串操作需要什么正则表达式?” 这是XY问题。

换句话说,他们从正则表达式是他们所需要的假设开始,但是最好使用split()(像perl的tr ///这样的翻译,其中字符被另一个替换)或split()更好。只是一个index()。


4

这是一个有趣的主题。
许多正则表达式爱好者似乎将公式的简洁性与效率混淆了。
最重要的是,需要大量思考的正则表达式对其作者产生了极大的满足感,使它立即合法化。

但是... 当性能不成问题并且您需要快速处理文本输出(例如在Perl中)时,正则表达式非常方便。同样,虽然性能一个问题,但人们可能不希望通过使用可能有错误或效率较低的自制算法来尝试击败regexp库。

除此之外,正则表达式受到不公正批评的原因有很多,例如

  • regexp效率不高,因为构建顶层不明显
  • 一些程序员“忘记”仅一次使用一次正则表达式即可编译多次(例如Java中的静态模式)
  • 一些程序员会尝试错误的策略-使用正则表达式的工作量甚至更少!

4

我认为学习正则表达式并保持正则表达式不受欢迎的原因是,大多数开发人员都很懒惰,或者大多数开发人员都依赖外部库来为他们进行解析...他们依靠google寻求答案,甚至在论坛中要求他们问题的完整代码。但是,当实施或修改/维护正则表达式时,它们只会失败。

有一种流行的说法:“朋友不要让朋友使用正则表达式来解析HTML”

但是就我而言,我已经使用Regex制作了完整的HTML解析器,我发现正则表达式在解析html字符串时在速度和内存方面都更好(如果您有一个想法,您将要实现什么:))


2
我认为注销大多数开发人员是愚蠢的……懒惰。我想说的是,这种语法非常隐蔽,不直观,并且充满了陷阱,这给未入门的人带来了很大的进入障碍。出于同样的原因,Perl对许多人都享有“坏”的声誉,但它也是一种非常强大的语言。就像尝试在知道符号之前先阅读数学表达式。这令人望而生畏,开发人员必须花时间进行司法工作,以了解他们将从学习该语法中受益。
Katastic Voyage,

错过HTML中的边缘情况,因为HTML不是常规语言。如果您打算解析HTML的已知子集,那将是安全的
Boyang

2

正则表达式对于包括我自己在内的许多人都是一个严重的谜。它的效果很好,但是就像看一个数学方程式一样。我很高兴地向您报告,尽管有人终于在http://regexlib.com/上创建了各种正则表达式函数的合并位置。现在,如果Microsoft仅创建一个正则表达式类,它将自动执行许多常见的工作,例如消除字母或过滤日期。


2
您错过了重点。正则表达式的想法是,您花费一些时间来学习它们,完成后,您不再需要一些神奇的“阅读日期”类。取而代之的是,它们很少花费正则表达式。此外,为“ yyyy / mm / dd”写一个,与为“ mm-dd-yyyy”写一个,甚至为“ mm-yyyy / dd”写一个,都将花费很少的精力(这赢得了“这种情况很少发生,但这只是一个例子,说明了您如何做神奇的课堂永远无法做的事情”。)
贾斯珀(Jasper

1

我发现正则表达式有时非常重要。当我需要进行一些“模糊”搜索时,也许会替换掉。数据何时可能变化并具有一定的随机性。但是,当我需要进行简单的搜索和替换或检查字符串时,我不使用正则表达式。尽管我认识很多这样做的人,但他们将它用于所有工作。那就是争议。

如果您想在墙上钉钉子,请不要使用锤子。是的,它可以工作,但是当您拿起锤子时,我可以在墙上放20个大头钉了。

正则表达式应用于其设计目的,无庸置疑。


0

尽管我认为正则表达式是必不可少的工具,但最令人讨厌的是它们有不同的实现。语法,修饰符和“特别是”“贪婪”之间的细微差别可能会使事情变得非常混乱,需要反复试验,有时还会产生令人困惑的错误。


正则表达式实现最大匹配的方式有什么不同,我认为您称之为“贪婪”的东西?您是说最左最长的语义和最长最左的语义之间的区别吗?这是我所知道的唯一区别;也就是说,贪婪胜过渴望,反之亦然
tchrist 2010年

0

在某些情况下,我认为您必须使用它们。例如建立一个词法分析器。

我认为,这是可以写正则表达式的人和不能(或几乎不)的人的观点。我个人认为这是一个很好的想法,例如,验证表单的输入,无论是使用JavaScript来警告用户,还是使用服务器端语言。


0

我认为这是程序员中鲜为人知的技术。因此,它没有被广泛接受。而且,如果您有非技术经理来审查您的代码或审查您的工作,则正则表达式非常不好。您将花费数小时编写一个完美的正则表达式,并且由于认为他/她已经编写了很少的代码行,因此您在模块上不会得到多少分。另外,正如在其他地方所说,读取正则表达式是非常困难的任务。


1
仅当编写正则表达式的程序员无法使用空格,注释,字母数字标识符以及可能还无法通过延迟执行来嵌入子例程时,读取正则表达式才是一项艰巨的任务。简而言之,所有适用于通用编程的软件工程技术也应遵循正则表达式。如果忽略这些原则,那么编写者就不会在编写专业代码。
tchrist

我认为您的经理不知道“编程的真正英雄是编写否定代码的人”。
拉杰夫

如果您的经理要用3行代码(包括正则表达式)来完成您的工作,同时赞扬在900行汇编程序中做到这一点的doofus同事,那么我建议您找一份新工作。
Phil Perry

0

诸如lex和yacc中用于编译器定义的体面正则表达式系统是很好,非常有用和干净的。在这些系统中,表达式类型是根据其他类型定义的。在perl和sed代码(等)中常见的可怕的畸形,无法读取的线噪声巨型单线正则表达式是“有争议的”(垃圾)。


-4

正则表达式的最佳有效和正常用法是用于电子邮件地址格式验证。

这是一个很好的应用。

在TextPad中,我无数次使用正则表达式作为一次性消息来处理平面文件,创建csv文件,创建SQL插入语句之类的事情。

编写良好的正则表达式不应太慢。通常,其他选择(例如,大量调用“替换”)的速度要慢得多。一口气也可以这样做。

在许多情况下,都需要正则表达式,而别无其他。

用无害字符替换特殊的非打印字符是另一种很好的用法。

我当然可以想象有些代码库过度使用了正则表达式,从而损害了可维护性。我自己从未见过。实际上,代码审查员避开了我对正则表达式的使用不足。


10
经验表明,正则表达式实际上是用于电子邮件地址格式验证的非常差的工具。实现为正则表达式的真正完整格式的验证程序是数百个字符的怪诞现象,而大多数人花5分钟才能创建的大多数较短的“足够好”的验证程序将拒绝大类有效的可交付地址。
Dave Sherohman

我听见伙计。我说的是“足够好”,虽然理论上讲可能会很大,但请考虑一下您在这么短的时间内所获得的覆盖率。我也见过怪兽,但是您的优雅选择是什么?
克里斯·莫利

2
我曾使用\ w @ \ w +。\ w +之类的方法在庞大的文件目录中快速找到电子邮件地址,在这些文件中,速度很重要,而误报或误报并不重要。但是,验证电子邮件地址的最佳方法似乎是向其发送电子邮件。
RossFabricant

是的,电子邮件地址说明是令人讨厌的混乱stackoverflow.com/questions/611775/…–
尼克·范布伦特

@ Nick,@ Dave:邮件地址验证不必是一团糟。
tchrist 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.