10

有一个类似的问题,但它只是得到了人们总是给出的关于正则表达式语法的相同旧答案,但这不是这里的重点,所以请尽量不要下意识地使用关于正则表达式语法的相同旧答案。这次尝试更加原创和个性化。

正则表达式语法非常紧凑,几乎太紧凑以至于不好。它就像代码打高尔夫球,每个人都同意打代码在生产代码中不是一件好事。然而,大多数人接受正则表达式语法,这似乎......至少可以说是矛盾的。

因此,现在人们可能会听到一些常见的防御措施,包括:

  • :很紧凑

  • Counter : 在这个时代,我们不是都同意代码应该是识字的,并且像“client”这样的变量比“c”更好吗?

  • :这是一种“特定领域的语言”

  • 计数器:所有非常容易理解、非紧凑、非神秘和我敢说漂亮的领域语言,比如 SQL 或 LINQ,怎么样?

  • :知道了就很容易理解了。

  • Counter : 大多数优秀的语言都很容易理解,即使您以前从未使用过它们。例如,任何人都可以很容易地跳入 Python,即使他们以前从未见过它。为什么人们在正则表达式如此难看的时候为它辩护,然后继续抱怨 Lisps 括号?

好的,现在每个人都尝试在这里保持原创和诚实,不要只是拿出 20 年前程序员用来设计正则表达式的老生常谈的答案。除非你真的相信它们是当今时代的有效命题。


编辑:为了记录,我从几年前就知道正则表达式,即使在今天也经常使用它们,甚至可能会摸索它们。然而,我突然有一种感觉,也许是时候重新考虑我认为关于正则表达式的“真相”了,并从现代的角度来看它们。主要是因为质疑原则是进一步发展的必要条件,而且因为很多新人对他们的强烈抱怨,他们不能一概而论,所以我决定试着站在一个新人的角度考虑一下有什么好的地方反对正则表达式。

至于主观性,我不认为这比当时的程序员笑话更主观或更少与程序员相关。相反,它与程序员非常相关。

至于争论,这就是问题的重点。为了获得好的论点赞成和反对正则表达式过时的语法,这可以让新手真正了解更多关于为什么正则表达式是它们的原因,甚至更好地希望让一些新手想出一个更好的解决方案,因为我们老思想看不到被正则表达式的“酷”蒙蔽了双眼。


引用:

正则表达式的 Perl 5.10 文档已经融化成一堆不可读的乱码,因为语法中出现了许多滑稽的特性,以至于没有人可以再为它编写合理的文档了。

你是想说正则表达式变得不可维护?那么作为优秀的程序员,我们应该考虑重构它们吗?也许像我们对许多其他技术所做的那样清理和尝试?

4

19 回答 19

35

我要说的大部分内容都由 Adam 和 DGM 解决,但我认为他们没有很好地涵盖你的第二点。

“所有非常容易理解、不紧凑、不神秘并且我敢说漂亮的领域语言,比如 SQL 或 LINQ,怎么样?”

我认为表达这个问题的一个好方法是问,你会如何用英语来解释正则表达式?

<TAG\b[^>]*>(.*?)</TAG>

寻找“<TAG”一个单词边界零个或多个不是'>'的东西,后跟一个'>'记住零个或多个东西,停在第一个“</TAG>”

这是一个相当简单的正则表达式。英文表格真的更容易理解吗?你能做得更好吗?

正则表达式很难阅读,但你想从它们那里得到什么也很难解释。

于 2008-11-05T05:04:23.213 回答
27

看看问题的另一面:你将如何设计一种新的语法来体现正则表达式的所有特性、一致性、简洁性和健壮性,但对程序员更友好?

于 2008-11-05T04:00:42.903 回答
18

你的反驳是似是而非的。你知道正则表达式语法,还是从无知的角度争论?建立你的偏见很重要。

  • 这根本不像打代码打高尔夫球。我不确定你在那里的联系。为什么不抱怨指针或其他使用相同参数的东西呢?

  • 正则表达式的紧凑性与糟糕的变量名无关。一个名为 c 的变量可以是任何东西。正则表达式语法既不模棱两可也不含糊。它准确地描述了它的模式。

  • 这是一个DSL。那么如果是呢?你有没有试过用 SQL 做复杂的事情?这也是一个大麻烦。做同样的事情需要更多的打字和更多的语法并不能改善这种情况。我教过的大多数人都遇到了正则表达式的问题,因为他们不习惯思考和设计模式,而不是因为语法是异国情调的。

  • 一旦你知道它就很容易理解。嗯,是的。电动工具并未针对新手或不愿学习的人进行优化。我不抱怨 Lisp 括号,但我不介意正则表达式语法。

如果您不想使用正则表达式,请不要使用。使用字符串操作函数或解析器。使用其他工具。当你忙于那个时,我将在你面前解决十个问题,因为我不会逆流而上,也不会将我无法完成的工作归咎于工具。

你想完成多少工作取决于你。找到让你最快到达那里的工具并学习它。如果你不喜欢那样,发明一些更好的东西。在那之前,停止抱怨。

于 2008-11-05T04:29:32.893 回答
17

这实际上是美国退休程序员协会针对当今在 Python 和 Java 上咬牙切齿的年轻人的阴谋。我们需要对神秘主义者保持敬畏和尊重,他们的聪明才智用三字符助记符克服了微小核心记忆和神秘语言的挑战……并且喜欢它。上坡……双向……在雪地里。:-)

于 2008-11-05T04:28:47.153 回答
11

我会捍卫正则表达式语法,因为它(大致)与我在学习算法和机器课程时学到的符号相匹配。这是一种生成机器以摄取指定常规语言的简单方法。

正则表达式语法就是这样,因为它确实是您完全描述您正在寻找的行为所需要的一切。

于 2008-11-05T04:14:44.577 回答
9

有用!!
如果有一种易于阅读的语言在每种主要编程语言中都有扩展,并且有充分的文档记录和测试,并且不像正则表达式那样压缩,但也不太冗长(冗长 = 烦人),我很想知道更多关于它的信息

于 2008-11-05T04:14:17.713 回答
8

正则表达式的一些问题不是语言本身,而是人们试图使用它们的目的。当他们真正想要的是一个相当简单的解析器时,他们会写一行又一行的正则表达式。

正则表达式非常适合简单到中等复杂的子字符串匹配和数据提取。但是在某些复杂点上,您只需要抽出编译器 - 编译器并编写一个真正的解析器。我认为很多人没有意识到正则表达式主要用于匹配,而不是用于解析。

于 2008-11-05T05:26:04.790 回答
7

您应该将正则表达式视为高端电动工具(我指的是建筑行业意义上的电动工具)。

如果你正在为你的棚子建造一个小工作台,你不会拔出射钉枪、电锯和工业路由器。你用一把锯子,一些钉子和一把锤子。

同样,您不会在某处没有起重机的情况下建造 30 层楼的建筑物。

我们的想法是为工作使用正确的工具,并您的技能水平使用正确的工具。

如果您必须砍伐一棵树,请确保在启动电锯之前了解所有有关回扣的知识。如果您不这样做,请改用手锯,省去去医院重新连接断肢的机会。

我像使用电锯一样使用正则表达式——非常小心。如果您对该工具感到不舒服,请不要使用它。一旦你学会了如何正确使用它,你会发现更快地完成工作会容易得多。

于 2008-11-05T04:18:56.377 回答
7

其他人已经暗示了这一点,但需要明确说明:

常规语言不像编程语言。它们更接近数学符号。

紧凑性和古怪性更多是由于试图从 ASCII 字符中强制使用精确的符号,而不是故意尝试简洁或混淆。

于 2008-11-06T01:03:54.260 回答
6

正则表达式的另一个问题是它有很多口味。.Net regex vs php regex vs 其他 regex,看起来都一样,但结果不一样(有时根本没有结果)。

于 2008-11-05T04:00:27.180 回答
6

我认为类似 SQL 的正则表达式语言将是一个令人着迷的项目。我很想看到有人创造它。

为什么没有一种可以写作的语言

LOOK FOR "<TAG"

THEN WORDBOUNDARY THEN ZERO-OR-MORE NOT('>') FOLLOWED-BY '>'

THEN ZERO-OR-MORE SOMETHING REMEMBERED

THEN NEAREST "</TAG>"

我不确定谁是目标受众——我不认为我会使用它,因为我一直在学习正则表达式。

当然,“需要使用如此复杂的表达式的人”几乎映射到每天必须处理同样复杂的事情的程序员?

于 2008-11-05T05:43:07.613 回答
6

Pyparsing ( http://pyparsing.wikispaces.com/Examples ) 是一个 Python 库,它可以轻松编写具有高度可读性的类似正则表达式的表达式,例如这些将解析“Hello, World!”的行:

from pyparsing import Word, alphas
greet = Word( alphas ) + "," + Word( alphas ) + "!"
greet.parseString("Hello, World!")

看起来该库非常接近能够匹配正则表达式的功能(请参阅上面提到的示例页面)。

于 2008-11-05T16:23:13.967 回答
5

它们类似于 BNF 表示法等,是许多良好语言规范的基础。因此,在词法分析器中使用这样的符号来表示预期字符的类别是有道理的。基本符号真的没有那么神秘。

然后我认为 UNIX-do-all-you-can-in-a-single-line 的想法占据了主导地位。在 sed 和 grep 脚本改进之后,正则表达式获得了新的权力,但它们的简写外延。Larry Wall 将它们合并到 Perl 中,作为解析文本的通用工具。我猜它保留了对于 perl 仍然很重要的 oneliners 的紧凑性。并且有通用字符类的简写名称,甚至更多的权力被要求和给予正则表达式。当然,由于 Perl 也是一种模块语言,因此正则表达式语法也适用于语句块,并且它利用了更广为人知的语法。

IMO 将它们纳入 Java 确实是人们关注它们的原因。Java 没有采取任何措施来适应它们。结果,中等难度的反斜线表达式变成了密集的反斜线丛林。如果你愿意的话,Java 给了正则表达式一个新的市场,但它是它们最残暴的形式。如果您已经看过这些并且没有更多关注,您可能会认为正则表达式是不应该的事情。

有趣的是,对于 Ambrose 的冗长版本,如果语法足够清晰,有人可以为 Perl 提供一个模块,该模块可以采用冗长的正则表达式并将其“编译”成 Perl 可以理解的紧凑正则表达式,通过使用更简单的正则表达式overload::constants或者可能是Parse::RecDescent语法.

于 2008-11-05T15:49:14.597 回答
4

就是这样……正如您正确指出的那样,主要是出于传统原因。现在

  • 再培训和重组:它已经获得了大量的追随者,即使有人愿意,它的根基也已经变得太深而无法进行大修。人们已经学会了神秘的规则,并开发了他们的技巧、社区和工具包(我插入 Expresso)。
  • 广泛的支持:当前的语法在平台上得到了广泛的支持。即使你不考虑编写自己的引擎和处理所有边缘情况的艰巨任务,重写这种支持水平也是一项艰巨的任务
  • Reg Exp 不太可能改变最后也是最重要的,RegExp 不能等同于代码的可读性。就我个人而言,我谨慎地使用正则表达式并进行快速切口,其优点大于好处。(例如,将客户的 Excel 电子表格刮成由开发人员设计的 XML 格式的内部工具。) 正则表达式不需要维护和修改.. 如果它非常复杂.. 用注释掩盖气味(和它应该只有一次)。如果您发现正则表达式被定期修改(或者如果您的工作场所没有其他人知道正则表达式),那么这可能是一个糟糕的选择,您应该切换到常规代码。

就我个人而言,我发现正则表达式(至少是日常任务所需的部分)很容易掌握.. 一天或 2 天。高级的东西很难(MasteringRegExp 书的后半部分),但你也不需要那么频繁。

于 2008-11-05T04:36:03.910 回答
4

正则表达式(至少最初是这样)描述了一种正则语言。正则语言具有非常好的理论特性,因为它们都可以通过确定性有限自动机来描述和描述。非平凡正则表达式的 DFA 很难手工编写代码。

更重要的是,perl等后端使用的正则表达式编译器非常擅长它们的工作。手动调整有竞争力的代码是非常困难的。

最后,它们的存在很大程度上是一个历史产物。他们已经存在了很长时间,获得了思想份额,很多人都认识他们。您拥有并且其他人可以支持的工具比尚不存在的理论工具要好得多。

如果只是语法让您失望,也许您应该考虑查看 Haskell 中的解析器组合器。它们可以表达相同想法的超集,并具有更明确的语法。

于 2008-11-05T16:09:42.247 回答
3

查看您提到的类似问题及其答案,我看到了一些尝试创建“更友好”的替代语法的尝试,来自我们今天所知道的正则表达式的支持者和批评者。

我发现它们比等效的正则表达式更易读。

现在,当然,我是正则表达式的常规用户,所以我确信我对它们的舒适度是其中的重要部分。但我对它们的主要问题不是不熟悉,而是它们很快变得太大而无法一次全部吸收。当你的 20 个字符的正则表达式变成一个 10 行 x 30 列的伪英语表达式时,就很难看出它的各个部分是如何相互关联的。

也许有人会想出一种替代正则表达式的语法,即使在复杂的情况下,它也更易于阅读,但我认为这种语法本质上需要一些与子例程调用等效的语法。我们不会编写具有 15 层嵌套逻辑的 200 行应用程序代码块,因为仅跟踪其逻辑将是一项艰巨的任务,更不用说弄清楚它实际上做了什么。如果我们要将正则表达式分解成更类似于英语的形式,那么同样的问题也会发生,我们需要同样的工具来管理它。

于 2008-11-05T15:57:21.460 回答
2

就像亚当说的,还有什么更好的吗?想到尝试做一堆 strcmp 操作而不是一个好的正则表达式,我不寒而栗。像任何表达性语言一样,可能会滥用正则表达式并制作非常不可读的结构,但通常即使是看似不可读的正则表达式也比实现相同目的的等效程序代码更有意义。

如果没有正则表达式,您必须编写自己的例程来解析、回溯、比较、存储索引、进行替换和管理所有结果。正则表达式以非常富有表现力的形式为您提供所有这些。我不喜欢重复代码,但是如果每次我需要寻找一个中等复杂的模式时我都必须编写自己的解析器......我不知道我会做什么。

是的,有不同风格的正则表达式,但大多数最流行的非常相似,而且无论您使用哪种语言,通常都有帮助您阅读的文档。

于 2008-11-05T04:15:09.943 回答
2

来自 perl 模块Regexp::English

Regexp::English 提供了另一种正则表达式语法,它比标准机制稍微冗长。此外,它还添加了一些方便的功能,例如增量表达式构建和绑定捕获。

    use Regexp::English;

    my $re = Regexp::English
            -> start_of_line
            -> literal('Flippers')
            -> literal(':')
            -> optional
                    -> whitespace_char
            -> end
            -> remember
                    -> multiple
                            -> digit;

    while (<INPUT>) {
            if (my $match = $re->match($_)) {
                    print "$match\n";
            }
    }
于 2012-05-31T04:14:32.570 回答
0

我敢打赌,本次讨论的所有参与者都会同意,对于某些的正则表达式代码,必须用英文写一长段来描述它的作用。任何一种可以用来做即使是最简单的正则表达式描述的语言都可能用 N 行代码来完成,其中 N(可能)与正则表达式本身的长度相比呈指数增长。

于 2011-11-29T15:23:42.137 回答