mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-17 14:43:42 +08:00
del
This commit is contained in:
49
极客时间专栏/geek/正则表达式入门课/开篇词/导读 | 余晟:我是怎么学习和使用正则的?.md
Normal file
49
极客时间专栏/geek/正则表达式入门课/开篇词/导读 | 余晟:我是怎么学习和使用正则的?.md
Normal file
@@ -0,0 +1,49 @@
|
||||
<audio id="audio" title="导读 | 余晟:我是怎么学习和使用正则的?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/3e/e9/3e238eff9dd032baa6yy37b0c78835e9.mp3"></audio>
|
||||
|
||||
你好,我是余晟。受伟忠的邀请,今天我来和你聊聊我是怎么学习和使用正则的。
|
||||
|
||||
刚工作那会儿,因为密集用到正则表达式,所以我花了不少时间去钻研正则相关的问题,因此获得了机会,翻译了《精通正则表达式》(第三版),后来又写了一本书《正则指引》。到如今,许多年过去了,这些东西还历历在目,我也很乐意拿出来和你分享一下,希望在学习正则的道路上,能给你一些启发。
|
||||
|
||||
我经常在网上看到,许多⼈抱怨正则表达式“难学”,我知道,它确实不好学。但同时,我也去看过大家的抱怨,发现和我之前的做法⼀样:用到什么功能,就去网上搜⼀个例⼦来改改,能跑通就满意。至于这例子到底如何构成的,自己是不是都懂了,其实心里没底,能大概看懂五六分,就已经很满足了。
|
||||
|
||||
这样浮光掠影的使用方法或许能解决眼前的问题,但⼀定不算“学会”。它有点像打井,每次挖到⼀点水就满足了,根本不管有没有持续性,也不关心挖没挖到含水层。结果就是,每次要喝水的时候,你都得重新打⼀眼井。
|
||||
|
||||
那么对于正则表达式,我们有没有可能打出一口“永不干涸”的深井呢?当然有,那就是**⼀次性多投入点时间,<strong><strong>由表及里,由术及道。一旦掌握了方法,之后就**</strong>会**<strong>简单很多了**</strong>。</strong>
|
||||
|
||||
按照我的经验,如果每天花一刻钟或者半小时,坚持个把礼拜,通常都能登堂入室,达到“不会忘”的境界。不要以为这时间很多,我知道有些人很喜欢找“正则表达式五分钟入门”,其实每次都没有入门,日积月累,反而浪费了几十甚至上百个五分钟。
|
||||
|
||||
那多投入时间很好理解,但是什么叫掌握方法呢?用我的话说,就是摆脱了字符的限制,深入到概念思维的层面。不要盯着那些鬼画桃符⼀般的字符和表示法皱眉,要摆脱桃符,把真正的“鬼”给认出来——虽然它们不那么容易看见。 也正因为这样,我们才需要⼀次性多投入点时间。
|
||||
|
||||
那最终怎样才算“入门”了呢?按照我的经验,就是通过学习掌握方法,后来无论用正则表达式解决什么问题,都能自发遵循下面的流程去走,甚至能达到不需要这个流程,也能做到解决问题,那基本上就算入门了。
|
||||
|
||||
**第⼀步,做分解。**拿到一个问题后,我们要先思考:这个问题可以分为几个子问题?每个子问题是否独立?我们拿最常见的电子邮件地址匹配来说。从文本结构来看,它可以分为“username + @ + domain name”这三个独立的部分。怎么画呢?我们可以先画出逻辑结构图。通过这个过程来厘清思路。当然,这是软件⼯程最基本的思路,相信你做起来应该问题不大。
|
||||
|
||||
**第⼆步,分析各个子问题。**某个位置上可能有多个字符?那就用字符组。某个位置上可能有多个字符串?那就用多选结构。出现的次数不确定?那就用量词。对出现的位置有要求?那就用锚点锁定位置…… 某种程度上,这就像武术里的见招拆招,每个问题都有对应的解法,只要熟练掌握了,知道什么时候用字符组,什么时候用多选结构,什么时候用量词,什么时候用锚点,就很容易搭建起完整的概念模型。
|
||||
|
||||
** 第三步,套皮。** 你大概注意到了,到现在,我们还没有谈论正则表达式的典型标志,比如方括号、星号、花括号。要知道,这些典型标志无非只是一些符号而已,真正重要的是字符组、多选结构、量词等等这些概念。一旦你的概念模型清楚了,写出正则表达式就非常简单了,无非是查阅语法手册,把之前得到的概念模型按照对应语言或工具的约定写下来而已。
|
||||
|
||||
许多人觉得正则表达式难懂,总是纠缠于“这里为什么要多一个星号?那里为什么是方括号而不是花括号?”,原因恰恰在于对概念模型不清楚。虽然各种语言或工具对正则表达式的支持大同小异,但细微差别仍然不可忽视。不过只要你心怀正念,洞若观火,这些差异其实并不是大问题。
|
||||
|
||||
**第四步,调试。**很多人都说,正则表达式的麻烦之处在于它像个黑箱子,很难调试,迄今为止仍然没有特别好用的⼯具,所以我们没法⼀步步跟进去看匹配的具体过程,只能笼统地知道“匹配了”或者“没匹配”。
|
||||
|
||||
那到底怎么调试呢?我的经验是,复杂⼀点的正则表达式不能⼀次写对,这是很正常的。与其纠结“这个正则表达式看起来这么复杂,此处到底要用星号*还是加号+,不如先搞清楚,星号( * )或加号( + )限定的到底是正则表达式中的哪一部分,对应要匹配文本中的哪一部分。这两个问题搞清楚了,整个问题就迎刃而解了。
|
||||
|
||||
另外,还有⼀点统摄全局的经验想和你说一下,** 那就是学会了正则表达式之后,务必要保持克制 **。写正则表达式很容易上瘾,毕竟它的功能那么强⼤,处理速度那么快,⼜像天书符咒那样充满了“神秘”色彩。于是,“写⼀条其他⼈看不懂的正则表达式,⼀次性解决所有问题”,就成了某些程序员的执念。但是,从软件工程的角度来看,这种办法绝对是噩梦,不但其他人无法理解,自己过⼀段时间也会挠头。
|
||||
|
||||
那到底该怎么“克制”呢?我的经验有以下三点。
|
||||
|
||||
**第⼀,能用普通字符串处理的,坚决⽤普通字符串处理****。**字符串处理的速度不见得差,可读性却好上很多。如果要在大段文本中定位所有的today或者tomorrow,用最简单的字符串查找,直接找两遍,明显比to(day|morrow)看起来更清楚。
|
||||
|
||||
**第⼆,能写注释的正则表达式,⼀定要写注释**。正则表达式的语法非常古老,不够直观,为了便于阅读和维护,如今大部分语言里都可以通过x打开注释模式。有了注释,复杂正则表达式的结构也能一目了然。
|
||||
|
||||
**第三,能用多个简单正则表达式解决的,⼀定不要苛求用一个复杂的正则表达式**。这里最明显的例子就是输入条件的验证。比如说,常见的密码要求“必须包含数字、小写字母、大写字母、特殊符号中的至少两种,且长度在8到16之间”。
|
||||
|
||||
你当然可以绞尽脑汁用一个正则表达式来验证,但如果放下执念,⽤多个正则表达式分别验证“包含数字”“包含小写字母”“包含大写字母”“包含特殊符号”这四个条件,要求验证成功结果数大于等于2,再配合一个正则表达式验证长度,这样做也是可行的。虽然看起来繁琐,但可维护性绝对远远强于单个正则表达式。
|
||||
|
||||
## 小结
|
||||
|
||||
好了,到此为⽌,我的经验介绍完了,可以交棒了。
|
||||
|
||||
这些年,很多人问过我,我当时到底是怎么学会正则的?说实话,我那会儿根本没想什么,纯粹出于“干一行爱一行”的朴素想法。要用得多,就找书来,哪怕是囫囵吞枣,也要一鼓作气看完。**我一直觉得,真正值得学的东西,没有什么“平滑学习曲线”。在前面的阶段,你总得狠下心来,过了一个又一个坎儿,然后才能有一马平川。**
|
||||
|
||||
我觉得,正则表达式属于“没有维护成本”的技能。一旦学会了,每⼀次遇到这类问题都可以“零成本出击”。所以,长期来看,这绝对是一笔“无本万利”的生意。希望你能通过这个专栏早日达到一马平川!
|
||||
93
极客时间专栏/geek/正则表达式入门课/开篇词/开篇词丨学习正则,我们到底要学什么?.md
Normal file
93
极客时间专栏/geek/正则表达式入门课/开篇词/开篇词丨学习正则,我们到底要学什么?.md
Normal file
@@ -0,0 +1,93 @@
|
||||
<audio id="audio" title="开篇词丨学习正则,我们到底要学什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/bf/4e/bf8d7d5bcdb495d3d22e6f5ae926904e.mp3"></audio>
|
||||
|
||||
你好,我是涂伟忠。从今天开始,我们就要一起来学习正则表达式了。
|
||||
|
||||
我相信,作为一名程序员或者准程序员,你肯定是知道正则表达式的。作为计算机领域最伟大的发明之一,正则表达式简单、强大,它可以极大地提高我们工作中的文本处理效率。现在,各大操作系统、编程语言、文本编辑器都已经支持正则表达式,甚至我还和极客时间的编辑开玩笑说,他们也应该好好学学正则这门手艺。
|
||||
|
||||
但是,当我去和朋友深入聊天的时候,才发现很多人是没有系统学习过正则表达式的,他们和我笑着说,这东西不难,我每次用的时候都是去 Google 搜一搜,然后复制过来改一改,效率特别高,我听完之后哭笑不得。
|
||||
|
||||
再后来,我和极客时间合作了一个关于正则表达式的每日一课课程,在课程的留言里,很多用户讲了他们的困惑,我总结了下,主要有4点:
|
||||
|
||||
1. 学过正则,但觉得过于复杂,根本记不住;
|
||||
1. 在网上找到的正则和自己的需求有一点出入,看不懂,也不知道该怎么改;
|
||||
1. 不清楚正则的流派和支持情况,搞不懂为何自己写的正则没达到效果;
|
||||
1. 不清楚正则的工作原理,结果写出的正则或者从网上随便找来的正则出现了性能问题。
|
||||
|
||||
为什么会出现这些问题呢?我觉得是核心原因主要是以下几点:
|
||||
|
||||
1. 没重视过正则,觉得没必要专门花时间学习,用的时候才发现“书到用时方恨少”;
|
||||
1. 没系统学习过正则,只简单地使用过部分功能,自然也就不清楚正则流派及工作原理等内容了;
|
||||
1. 没找到正确的方法去学习和记忆,导致学了之后很快就忘了。
|
||||
|
||||
所以,我打算通过一个课程,用尽可能通俗易懂的方式,系统化地给你梳理和讲解正则的知识点,希望可以帮助你解决上面这些问题,让正则这个强大的工具在你手上发挥出真正的威力。
|
||||
|
||||
但是呢,真要开始学正则,我想你的心头可能会五味杂陈,内心也是纠结万分。美国一位知名程序员杰米·加文斯基(Jamie Zawinski)说过一句话:
|
||||
|
||||
>
|
||||
[如果你有一个问题,你想到可以用正则来解决,那么你有两个问题了。](http://regex.info/blog/2006-09-15/247)
|
||||
|
||||
|
||||
>
|
||||
Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.
|
||||
|
||||
|
||||
这句话流传在程序员中间,给人一种感觉,就是正则是很难掌握和利用好的工具。也正因如此,很多程序员并不愿意去学正则表达式,心里可能是这么想的:我在工作中用到正则的时候并不多啊,要用的时候搜一下就好了啊,为什么还要专门花时间和精力学它呢?
|
||||
|
||||
但我觉得,真实的情况可能是这样的:**不是工作中用不到,而是当你不熟悉一个技能的时候**,**遇到问题时根本不会考虑它**。比如我们要删除掉文本中的所有数字,不知道正则的话,你可能会想到从0到9这样一个个替换,操作10次,但如果知道正则,那么只需要替换一次就可以搞定这个问题。
|
||||
|
||||
## **正则是什么,能做什么?**
|
||||
|
||||
说了这么多,到底什么是正则呢?它能做什么呢?
|
||||
|
||||
我们先来说概念。正则,就是正则表达式,英文是 Regular Expression,简称 RE。顾名思义,正则其实就是一种**描述文本内容组成规律的表示方式**。
|
||||
|
||||
在编程语言中,正则常常用来简化文本处理的逻辑。在Linux命令中,它也可以帮助我们轻松地查找或编辑文件的内容,甚至实现整个文件夹中所有文件的内容替换,比如 grep、egrep、sed、awk、vim 等。另外,在各种文本编辑器中,比如 Atom,Sublime Text 或 VS Code 等,在查找或替换的时候也会使用到它。总之,正则是无处不在的,已经渗透到了日常工作的方方面面。
|
||||
|
||||
简单来说,正则是一个非常强大的文本处理工具,它的应用极其广泛。我们可以利用它来校验数据的有效性,比如用户输入的手机号是不是符合规则;也可以从文本中提取想要的内容,比如从网页中抽取数据;还可以用来做文本内容替换,从而得到我们想要的内容。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/da/68/da861b19b09731c29d1882fea6c25b68.png" alt="">
|
||||
|
||||
通过它的功能和分布的广泛你也能看出来,正则是一个非常值得花时间和精力好好学习的基本技能。之前你花几十分钟才能搞定的事情,可能用正则很快就搞定了;之前不能解决的问题,你系统地学习正则后,可能发现也能轻松解决了。
|
||||
|
||||
## 学习正则,我们到底要学什么?
|
||||
|
||||
那么问题来了,想要掌握正则,我们到底要学什么?我在课程中又是怎么安排这些内容的呢?
|
||||
|
||||
### 1.正则的基本知识
|
||||
|
||||
正则的很多基本知识其实并不难,只是难记。不过,记住一个东西并不是我们的最终目的,我们的目的是理解并且会用正则这个工具。
|
||||
|
||||
比如正则中的各种元字符,在课程中,我会讲有关元字符的记忆技巧,让你不再对元字符感到头疼。再比如各种模式和分组,它们可以在查找和替换时发挥强大的威力。
|
||||
|
||||
下面我用Python语言示例,从文本中找出连续出现的重复单词。我们可以看到,正则可以很方便地搞定这个需求。
|
||||
|
||||
```
|
||||
>>> import re
|
||||
>>> test_str = "the little cat cat in the hat hat."
|
||||
>>> re.sub(r'(\w+) \1', r'\1', test_str)
|
||||
'the little cat in the hat.'
|
||||
|
||||
|
||||
```
|
||||
|
||||
但上面的示例在任何情况下都能很好地工作么?我们要不要考虑单词的边界?反向引用又有哪些要注意的点?所有这些问题都会在课程中一一进行讲解。
|
||||
|
||||
### **2.<strong><strong>在常见的编辑器中**</strong>使用正则的方法</strong>
|
||||
|
||||
我们经常需要从大段文本中抽取需要的内容,学会使用正则之后,不用写代码就可以完成类似的日常工作。举个例子,假如我们在Sublime Text 3 中使用正则,查找重复出现的单词,并且想把它替换成单个单词。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/53/35/5389df52d6007ed1f5c9b52f5ba4da35.png" alt="">
|
||||
|
||||
菜单中的 Find -> Replace,在查找栏中输入 (\w+) \1,在替换栏中输入子组的引用 **\1** ,然后点击 Replace All 就可以完成替换工作了。这样,通过少量的正则,我们就完成了文本的处理工作了。是不是很方便呢?
|
||||
|
||||
### **3.正则中进阶的内容**
|
||||
|
||||
除此之外,我还会在课程中讲一些更高阶的正则内容,这部分主要有正则中的断言(包括单词边界、行开始和结束、环视),三种主要流派的区别以及对应的软件实现,正则的工作机制和常见的优化方式等。
|
||||
|
||||
掌握这些内容可以让我们更好地理解正则, 也可以避过很多坑。比如,为什么在编程语言中能工作的正则,在Linux命令 grep 中就不能工作了呢?正则匹配的原理又是什么?如何写出性能更好的正则呢?
|
||||
|
||||
综合以上这三点,我希望你能掌握的是正则中一些重要的概念和功能,这是我们学习和使用正则的基础;然后是有关正则的记忆方法,通过合理的方式,事半功倍地达到学习效果,这是我们学习正则的利器;此外,我还会运用大量的示例让你了解正则在实际工作场景中的使用,只有与现实案例结合,我们的学习才不会脱节,这是我们学习正则的原则。
|
||||
|
||||
明确原则、打好基础、掌握利器,我相信你一定可以拿下正则这项技能,在工作中随心所用。学完后,你一定会觉得,手写正则原来也没有那么难。
|
||||
|
||||
话不多说,我们这就开始吧!
|
||||
Reference in New Issue
Block a user