您如何学习正则表达式?[关闭]


80

我不是问在哪里学习。我在网上找到了很多很好的资源,还有书籍等。

但是,我该如何解决这些问题。起点在哪里,终点在哪里?regexp处理器何时在文本上前进,何时保持立场并尝试其他匹配?等等

我想尝试找出埃及金字塔上的象形文字。


2
排序对主题- regular-expressions.info。在下面使用此和@Jalayn的建议。通过实践学习!
Freiheit

6
gskinner.com/RegExr是我发现的开发正则表达式的最佳工具。
卡勒姆·罗杰斯

一次一点。从简单的内容(“ aaa”,“ aa。”,“ a * b”等)开始,然后逐步发展到实现特定的组件(即PCRE)。然后提出一个模式,并尝试制作一个适合它的正则表达式。
tylerl

我通过试验和错误学习了很棒的程序RegexBuddy。regexbuddy.com(我不以广告宣传此信誉,该程序确实使它易于学习)
Yam Marcovic

rubular.com是开发正则表达式的好工具。
Gazler 2011年

Answers:


68

我认为自动机理论的知识对于理解至关重要。

一旦了解了自动机是什么,以及如何定义正则语言,了解正则表达式将变得更加容易。

至于具体的语法和各种实现之间的区别……好吧,您只需要记住一些事情。也有帮助

编辑

以下一些评论提出了重要观点:

  1. 不要忘记,正则表达式(在大多数编程语言中已实现)是自动机理论中正则表达式的超集。虽然良好的理论背景是一个有用的起点,但它并不能告诉您所有信息。(谢谢David Thornley)

  2. 多个评论者说,无需学习理论基础就可以学习各种正则表达式语法。虽然确实可以在不完全了解语法工作原理的情况下学习语法,但我的印象是,对语法的充分理解才是OP所追求的。问题是关于实际基础的:处理器何时升级?什么时候停止?如何确定其匹配项?那是基础,那是理论,它是基于自动机理论的。当然,您可以在不知道发动机工作原理的情况下驾驶汽车。但是如果您被问到“气体实际上是如何驱动的”-您必须谈论发动机的构造,不是吗?


评论员:如果您想讨论这个问题的重点,请使用chat。否则,请考虑留下答案或对您认为最正确的答案进行投票。

感谢您的修改。这使这个答案更加接近事实。尽管我仍然认为您确实不需要了解自动机理论(我不知道,但是我仍然可以编写复杂的正则表达式),但我确实同意一些有关该理论的知识可能会有所帮助。尤其是了解回溯是如何工作的以及如何由贪婪/不满/占有量词控制的,可能确实有助于您的理解。
NikiC 2011年

只是我的2美分:在MSDN的Channel 9上有关C ++ STL regex库的最新视频系列中,主持人(也是STL的维护者)说,他们将其实现为自动机。因此,了解此理论确实可以使OP对regex的工作原理有一些见解。
korbes 2011年

5
我完全不同意开幕词。当我学习正则表达式时,我对自动机理论一无所知。三十年后,我仍然没有。我所知道的是如何阅读手册页,从字面上看,以及如何迅速进行尝试。
Bryan Oakley

1
@Bryan好...您的经验证明了这一点。您可能知道如何使用它,但您并不真正了解它是如何工作的。如果您这样做了,那么即使您不知道它的名字,您也会对自动机理论有所了解。但是在不了解自动机理论的情况下,您无法完全理解正则表达式,并且那里没有多少手册手册可以为您提供帮助(当然,除非您正在阅读解释自动机原理的手册页)。
littleadv 2014年

36

通过练习。

我通过玩网络抓取而学到的。我敢肯定,我并不是一个人只是为了好玩而已。

一个示例:编写一些代码,从您最喜欢的体育网站上检索最新的足球,网球(实际上是您喜欢的运动)得分。通过编写一些代码来加载页面,使用正则表达式提取分数并将其输出到控制台或某些文本文件来完成此操作。确保使用选择的正则表达式仅检索分数,而没有其他内容。有时,这可能是非常具有挑战性的:-)

第二个示例:编写一些代码来检索您喜欢的网络漫画的图片(例如,我非常喜欢Sinfest)并将其存储在硬盘上的某个位置。仅使用正则表达式检索“ img”标记及其内容。如果标题存储在某个地方,也可以选择检索其标题。


15
用正则表达式解析HTML 通常不是一个好主意。
2011年

10
当然,这是一个坏主意。应该“通常”使用DOM / Sax解析器或其他专用的XML阅读器。但是这里的主题是关于学习正则表达式的,我分享了我如何以“有趣”的方式学习正则表达式的方法。
Jalayn 2011年

3
与将XML解析器用于HTML网页相比,使用正则表达式将其解析更为糟糕。
skolima 2011年

8
嗯,我想更精确地说明自己的想法,但是我很懒,我只是对评论做出了反应……我想我们都可以同意1.使用正则表达式解析整个文档是一个坏主意2.使用XML解析器解析HTML是一个坏主意3.使用XML解析器解析XHTML是正确的4.使用正则表达式从HTML检索单行代码或某些非常特定的信息是正确的。或者我可以总结一下:适合正确工作的正确工具...
Jalayn 2011年

23

我知道您不是在请求资源,而是Jeffrey EF Friedl的Mastering Regular Expressions掌握正则表达式)是我学习它们如何工作以及如何使用它们的方法。甚至在使用了很多语法分析不同事物的意义之后,第一章对我来说还是新事物。

您想了解那些该死的正则表达式吗?读这本书。


2
这应该是明确的答案。
苗条

1
+100,000有史以来最好的技术书籍之一,有关问题的话题很方便。
2011年

喜欢这本书。关键在于它帮助我了解了Regex中可用的所有不同功能。阅读一本书将无法记住所有的语法,但是该书将向您展示所有存在的内容,因此您知道解决问题时必须使用哪些工具。
Kibbee

对此答案绝对+1。我在正则表达式上大吃一惊,直到我终于坐下来,逐行阅读了这本必不可少的书。现在,弗里德尔为我提供了足够的基础,让我可以通过困扰今天的所有许多非标准变化来说明自己的方式!我强烈建议将此参考引用给OP和其他所有人。也向@slim +1为其发表评论!
John Tobler

19

起点在哪里,终点在哪里?regexp处理器何时在文本上前进,何时保持立场并尝试其他匹配?等等

我首先要澄清您的目标,然后弄清楚您的学习风格

我对您的问题感到震惊的是,您问“我如何学习正则表达式?” 然后立即提出“正则表达式引擎如何在内部工作”的问题。您似乎在暗示这两件事是相互关联的,这很明显。也许您是一个通过分解或自己构建来学习事物工作方式的人。

对于初学者应用程序,通常无需了解工具的工作方式即可有效地使用它。您无需知道钻孔电机如何在木头上打孔;你需要了解如何使用钻,而不是如何建立一个钻。

那你的目标是什么?您是否打算学习如何构建正则表达式引擎?或者您打算学习如何有效使用正则表达式解决业务问题? 实现这些不同的目标可能需要不同的学习技巧。

要解决有关正则表达式引擎如何工作的特定问题:这取决于。正则表达式的“经典”理论方法是将正则表达式用作非确定性有限自动机的蓝图,然后构建等效的确定性有限自动机,然后对输入执行该自动机。

实际上,出于以下几个原因,几乎没有人这样做。首先,将状态数乘以可能的输入字符数将得出一个状态转换表,即使对于小的正则表达式来说也是如此。当然,大多数可以压缩,但是仍然有很多过渡规则。其次,其他方法通常更快。第三,所谓的“正则”表达式在现代的regexp库中不存在。它们根本不是普通语言。它们通常被下推自动机而非有限自动机语言识别。

(我开始写一长篇有关这些东西如何工作的系列文章,但是仅在前十二篇文章之后我就筋疲力尽了。如果您想对基本正则表达式的理论背景做一个简短的入门,可能会发现它们很有趣。)

实际的正则表达式引擎通常使用回溯策略。十多年前,我们为JScript引擎构建的正则表达式引擎现在将正则表达式编译为字节码语言,其中包括用于识别序列和回溯到较早状态的原语。然后,我们为该字节码语言构建了一个解释器。

在了解如何使用正则表达式之前,我不会尝试了解正则表达式引擎的工作原理。在开始研究各种不同引擎的优化策略之前,请先集中精力。


+1是因为您解决了一些使用正则表达式时应该知道的事情;但是,我不同意您的判断,即不必了解内幕。对于钻孔,您完全正确;在计算机中,我发现比起初想的要早,我必须了解一些内部知识才能掌握其应用程序-无论是C ++(编译器),Web服务器(HTTP)还是regexes(自动机理论) 。并不是达到成为专家的程度,而是对基本原理的充分理解通常是最快的学习方法。
Felix Dombek

3
@Felix:我认为我们实际上同意。我说过,对于初学者应用程序通常不需要了解该工具的工作方式才能使用它。那些鼬鼠的话是故意的。对于熟练工熟练的使用工具,这是非常有帮助的至少了解一些关于它的内部,这样就可以准确地预测该工具将有不好的表现,说。
埃里克·利珀特

嗯,我不得不不同意。我构建的一些最有用的业务程序已经使用了我在lexx和yacc中学到的理论来有效地解决问题。您说得对,但没有必要全面了解博士学位。我必须阅读博客文章,它们看起来最有趣。
斯宾塞·拉特布恩

您说正则表达式不是正则表达式-但我认为名称中的世界正则表达式是指它所匹配的表达式-例如"[0-9]{3}"可以匹配任意三位数字的正则表达式,而三位数字480是正则表达式的一个示例匹配的表达式。
配置工具,

1
@configurator:根据定义,“常规”语言是可以由有限自动机识别的语言。每种常规语言都可以通过仅包含并集,替代项,连词和Kleene Star的“正则表达式”来表征。但是如今,大多数“正则表达式”引擎都比正则语言识别更复杂的语言。例如,“带有正确匹配的括号的句子”的语言不是常规语言,但是您可以在某些正则表达式引擎中将其与“正则表达式”进行匹配。
埃里克·利珀特

6

我该如何应对?

像任何新事物一样:

10 Study
20 Practice
30 goto 10

研究

我发现,大多数成功的老师首先会提供一些背景知识,从而开始教授任何学科。了解您正在学习的内容以及最重要的是为什么要学习它是很重要的。

这都是字符串匹配

正则表达式是匹配文本模式的一种方式。它本身是一种声明性语言,已集成到许多其他编程语言中。

我想强调,这是一个说明性语言,正则表达式表达有用的东西来匹配字符串,但他们不以任何方式表达怎样的计划是去这样做的匹配。因此,只需使用不同的RegEx解析器,就可以在同一编程语言中非常快速和非常慢地使用正则表达式。

创建正则表达式的原因与大多数编程语言的创建相同:程序员发现自己一遍又一遍地执行相同的复杂任务,并决定他们想要一种更简单的代码编写方式。

有些人会(并且应该)抱怨我的前一句话,其方式如下:

RegEx不会使程序更简单。

这是真的

RegEx 不会使程序变得更简单,RegEx会使程序的编写变得更简单。您仍需要在测试中进行彻底检查,以确保所有正确的案例均正确匹配,而所有错误的案例均未匹配。测试“全部”真的很困难,而使用复杂的模式,测试“大多数”真的很困难。最糟糕的是,您仍然应该测试“某些”情况。

让我们结合一些我不得不选择JavaScript的RegEx引擎的示例,因为我可以轻松地在浏览器中对其进行测试,并且因为在使用RegEx文字时无需进行任何转义字符串。

当您进行正常的字符串匹配时,您将一个字符串值与另一个字符串值进行测试。它们可以来自任何地方,但最终需要将两个字符串与另一个字符串进行比较:

if ( 'foo' == 'bar' ) doSomething();

这个例子很烂,因为它永远不会任何事情

if ( foo == 'bar' ) doSomething();

好多了; 现在,我们实际上并不提前知道是否会做某事。现在我们可以开始接受用户输入了:

if ( prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();

bar令人惊奇的是,现在用户可以输入内容,并且会发生一些事情,直到您收到用户的错误报告,指出它们"bar"不起作用或“ BAR”不起作用,或者他们键入了BRA100次而没有任何反应。

忽略拼写错误和多余的字符,'bar' != 'BAR'程序员需要考虑一种测试字符错误情况的方法。

简单的解决方案,使用toLowerCase。效果很好,但是当您匹配时,使用英式英语而不是美式英语的用户又如何something == 'color'呢?现在您必须匹配something == 'color' || somthing == 'colour'

长话短说,简单的模式很快就会变成大量重复的代码。

颜色示例可以简单地与以下内容匹配:

/colou?r/.test( something )

对正则表达式的基础知识有扎实的了解,可以大大减少您浪费大量时间重新发明轮子。

在哪里学习

大多数实现正则表达式的语言至少都有一种资源可用于在该语言中使用正则表达式的特定语法。在MDN上可以找到一种JavaScript

阅读。
所有的。
然后再读一遍。

学习需要花费时间,将其视为一项投资:学习RegEx一个小时现在可以在下次需要进行一些字符串模式匹配时节省一个小时,然后在下一次节省一个小时。

实践

在阅读了有关RegEx的全部内容之后,您可能不会了解其中的大部分内容。那是因为您实际上并没有任何事情。

我提到了为什么我在本示例中选择JS,敦促您在浏览器中对其进行修改。速度很快,您可以直接在网址栏中进行操作。

JS有几种不同的使用RegEx的简单方法:

string.match( regex )
regex.exec( string )
regex.test( string )

从简单的东西开始:

javascript:'color'.match(/colou?r/);

是您踏进门的简单方法。试一试,打破它,看看什么匹配,什么不匹配。

当您坚持练习时,请继续30。您需要阅读以了解更多信息,但您需要进行练习以真正了解所学内容。


+1,用于建议在浏览器中使用JavaScript。
John Tobler

5

Brian Kernighan在《Beautiful Code》一书中编写了一个简单的正则表达式处理器。我意识到您不是在寻找资源,但是在内部看到一个基本的实现可能会有所帮助。


提到的“正则表达式处理器”实际上并没有实现析取,并且使用给定的方法很难添加它们。我喜欢这本书,但这是令我失望的一件事。
Felix Dombek

4

在常规开发中,调试代码可以提供非常有用的见解。正则表达式没有什么不同。因此,冒着听起来像是广告的风险,请获取RegexBuddy。它有一个很棒的工具,可以直观地显示引擎在处理表达式和输入字符串时正在做什么。


1
+1,“ Regex Hero”也很不错:regexhero.net/tester
Angelo

Regexbuddy是我最喜欢的工具之一。看到树视图非常有用,因为在生成正则表达式时可以立即进行测试。我已经学到了很多正则表达式,而没有尝试仅通过使用它来学习。

1
我一直觉得RegexBuddy很有趣,但是我不喜欢购买它。对于基本的正则表达式测试,还有许多其他实用程序。用于查看正则表达式的文本描述,尽管工具较少。Regex Hero的付费版本也可以。Regex调试器是RegexBuddy相当独特的一件事,它显示了每个字符的接受或拒绝以及详细的回溯,这在消除大型且非常复杂的正则表达式时确实有帮助。我还没有注意到有其他工具可以做到这一点。
凯文·卡斯卡特

3

正则表达式很快就会变得非常复杂,因此建议您使用教程开始学习。知道正则表达式最简单的形式是代表您要搜索的字符串。不幸的是,为了能够定义特殊的搜索规则,它需要某些字符,并且必须对这些字符进行转义,否则您将创建无效或不正确的正则表达式。

我的建议是从您要搜索的示例开始,然后转义它。因此,换句话说,如果您要查找括号中的任何内容,请以您要搜索的文本中的一个这样的字符串为例: (this is an example of something you'd want to find)

首先转义字符,以便搜索文字字符: \(this is an example of something you'd want to find\)

测试它,验证它可以正确找到您的示例。然后,对表达式进行泛化以查找任何此类文本,而不仅仅是找到的示例。因此,它将变为:( \([^)]*\) 表示任意数量的出现(包括0)都不是“”的任何字符)。

再次进行测试,并验证它不仅可以找到您的示例,还可以验证其他示例。在Internet上搜索更复杂但更频繁的正则表达式,并使用您现有的正则表达式对其进行修补,从而不必担心每种可能性。

就是这样 哦,学习并爱\ Q ... \ E。在大多数正则表达式语言中,\ Q表示文字模式的开头,\ E表示结尾,以防万一您必须搜索特别复杂的模式而又不知道如何转义它们。那挽救了我的生命不止两次。


3

我将为您提供一个简单问题的简单答案。首先,您需要了解什么是正则表达式(RegEx)-它们的作用以及它们的用途。然后,这是一个入门的好工具。

  1. 它是什么?RegEx是用于表达模式匹配的语言。就是说,使用它,您可以创建识别或发现文本模式的字符组合。这有什么用?在编程中,您可以告诉计算机匹配来自某些来源(用户输入,网页等)的文本,并检测其中是否包含特定的文本格式。例如,句点(。)代表任何字符-字母或数字。花括号中的数字表示迭代次数,因此“。{1,30}”表示任何字符,重复1到30次-换句话说,您不能有一个空字符串,并且长度不能超过30字符。它从那里继续。

  2. 如何开始学习?我见过的绝对最好的工具是Expresso,但这仅适用于Windows。它具有非常广泛的GUI,您可以在其中单击要添加到表达式中的元素,然后使用测试器根据各种输入对其进行检查以查看结果。我没有在Mac上看到任何好东西(但是我在VMWare上运行Windows,因此实际上并不需要Mac版本),也没有花很多时间在Linux上。


1
感谢有关Expresso的提示。我尝试了一下,真棒!
吉姆在德克萨斯州2011年

3

除了提供良好的参考以外,您真正学习的方法是使用良好的学习工具。一种是使用开源Vim编辑器,并设置了两个选项:

  1. :set incsearch ...当您在命令行中输入搜索模式时,编辑器会即时跳转到匹配的第一段文本,并突出显示完全匹配的文本。如果键入的内容不再匹配,Vim会将光标跳回到开始时的位置。
  2. :set hlsearch ...这告诉Vim在与当前RE搜索匹配的所有文本上显示突出显示的背景。

另一种是使用免费工具RegExCoach。您粘贴要搜索的文本,然后在另一个窗口中开发正则表达式。像Vim一样,它突出显示了成功的比赛。


RegExCoach现在是共享软件。我发现这对开发复杂的Perl风格的RE非常有帮助。
Firstrock,2011年

2

您首先进行基本的字符串比较。很简单,但也没有那么强大。

接下来,您可能已经想过,需要区分大小写比较,以便“ greek”和“ GreeK”比较相等。这有点强大。

有一天,您会发现拼写上的细微差异不应阻止两个单词比较相等:即“ organize”和“ organize”应该比较相等。您坐下来并编写一些实现此目的的代码,您会感到很高兴。

直到您多一点抽象并意识到有时您希望所有以“ ize”结尾的单词都与他们的兄弟在英语拼写上相等。或者,某些字符串重复一定次数。而且,当然,您需要结合所有这些。

等等。最后,您很有可能最终得到一些注释,其中并非每个字符都代表自己。没什么是正则表达式。可以将其视为一组字符串的描述。

然后,这很容易,可以归结为以下3个基本原则:

您有基本的正则表达式:代表字符的字符,字符类,方便的字符类缩写,例如\ d或\ p {Lu}大写字母。

然后,您可以将它们组合在一起:如果r1和r2是正则表达式,则r1r2 r1 | r2(r1)也是如此。

最后但并非最不重要的是重复修饰符:r?r * r + r {n,m}

这是您最需要知道的。您可以在需要时查找其他任何内容。


2

另外两个很好的答案告诉您学习正则表达式背后的理论并进行实践,它们都是不错的建议。如果您是认真的人,我也建议您使用一个好的视觉正则表达式工具来帮助您。

例如,RegexBuddy具有视觉调试模式,可让您逐步执行正则表达式的执行,并通过突出显示和说明性文本向您显示正则表达式引擎在每个步骤中的工作。他们的网站上有一个视频演示了此调试过程



1

对我而言,在我构建正则表达式时看到其匹配的内容确实有助于我的生活,并帮助我更好地理解它们。

为此,我将在Emacs中打开包含目标文本的文件,然后使用isearch-forward-regexp命令。当您输入正则表达式时,Emacs会向您显示其匹配的内容(这是“ isearch”部分)。

要运行命令,请在Emacs中使用<ESC>xisearch-forward-regexp


1

我通过学习flex和bison来学习正则表达式,而flex和bison用于构建词法分析器和解析器。没有正则表达式,就不可能有一个解析器,而lexx和yacc这本书非常擅长于不费吹灰之力地完成理论研究。

从根本上讲,这些天实际上所有正则表达式引擎都遵​​循相同的原则。它们都是有限状态机,如果您真正理解了这一点,那么您几乎可以编写任何代码。它类似于学习递归,一旦获得递归,便可以将其本能地应用于问题。使用正确的工具很容易解决问题,但是如果没有正确的工具则很难解决。

与正则表达式相比,学习lexx和yacc的另一件事是您了解它们内部如何工作。程序的前瞻性,完成比赛的原因,保存数据的方式等等。了解指针是绝对必须的,但是如果您掌握了lexx和yacc并从一开始就进行了遍历,那么您将学到您所要求的一切,并且拥有一个功能强大的工具,可用于您的其余职业。

这个问题包括大量学习资源,以及我扔在一起的flex骨架。


1

再次,我首先尝试确保没有更简单的方法来解决问题/“使字符串变”。

当您找不到一个时,我将其视为一个问题,而不是尝试从字符串中匹配您想要的内容,而是不匹配您不需要的内容。这主要是因为正则表达式是贪婪的。但这很好地为我提供了获得我想要的方法。

这是一个例子:

string = "Sep 22 19:57:38 host fcron[9137]: \
          Job fbsetbg -r $HOME/backgrounds/ \
          started for user user (pid 9138)"

匹配分钟:

string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/                 # correct and good

与其去寻找时间,不如去寻找与众不同的界限。

这个例子有些人为,但是我可以提出。


1

我使用的一种方法是找到一堆需要语法更新的开源项目,然后编写一个越来越复杂的sed脚本,该脚本由许多正则表达式组成。

该脚本需要针对每个开源项目中的许多不同文件运行。然后针对具有不同样式的许多不同项目运行。我从一个非常简单的东西开始,%s/before/after 然后发现它匹配太多案例。所以我添加了更多的东西来防止这种情况。然后,我发现使用不同语法样式的不同项目需要进行不同的更改。

最后我最终得到了

  • 关于正则表达式的精湛技巧和知识
  • 精通sed
  • 帮助许多开源项目
  • 在我的github个人资料上显示了很多贡献活动
  • 虚拟工具带的另一个很好的“瑞士军刀”工具

并且由于需要

  • 在不作弊的情况下实现实际目标
  • 将(regex)技能作为更大目标的一部分,并且具有更大的动力。
  • 能够通过更改其他代码然后审查更改来证明我学到的技能。

我还将顺带一提,有很多网站可以支持各种语言-红宝石,JavaScript等,使您可以随意处理表达式和示例文本,以备不时之需。这些是:

一个站点上多种语言的正则表达式

关注比赛组:


0

我发现学习正则表达式类似于学习乘法表-是的,您需要了解其背后的思想,但最终,您只需要经常重复进行此操作即可。

当我学习时,我将自己设定为每天进行几次正则表达式练习的目标。实际上,这意味着至少每天一次,我将尝试查看屏幕上的字符串或文本,然后提出一个挑战-“我可以从这里获取所有电子邮件地址”还是“找到所有“代码”一词用作动词而不是名词的出现。”

这样做了几个星期确实很有意义-当然,需要定期检查和复习。我要交一个。

我发现此在线工具也很有帮助,因为它让我实时测试了正则表达式:http : //www.gethifi.com/tools/regex

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.