正则表达式十步通关

推荐阅读:

编程神器 VS Code,只要这一篇就够了!

自由软件江湖里的码头和规矩

自己动手写一个操作系统内核【内含视频】

在浏览器中输入网址按回车后发生了什么?

智能制造:从信息化到智能化

一文透析华为鸿蒙科技含量!华为的创新必将刺激国内外巨头跟进

本文作者孟宁,未经许可禁止转载!

为什么使用正则表达式?

74a2390874c82a8e73a023a4721a6750.png

正则表达式(Regular Expression)是对字符串操作的一种逻辑公式。正则表达式的应用范围非常之广泛,最初是由 Unix 普及开来的,后来广泛运用于 Scala、PHP、C# 、Java、C++ 、Objective-c、Perl、Swift、VBScript、Javascript、Ruby 以及 Python 等等。学习正则表达式,实际上是在学习一种十分灵活的逻辑思维,通过简单快速的方法达到对于字符串的控制。可以说正则表达式是程序员手中一把威力无比强大的武器!

正则表达式大有用处,我们这里简要介绍几种常见的用途:

  • 测试字符串内的模式。可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。

  • 替换文本。可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

  • 基于模式匹配从字符串中提取子字符串。可以查找文档内或输入域内特定的文本。例如,您可能需要搜索整个网站,删除过时的材料,以及替换某些 HTML 格式标记。在这种情况下,可以使用正则表达式来确定在每个文件中是否出现该材料或该 HTML 格式标记。此过程将受影响的文件列表缩小到包含需要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料。最后,可以使用正则表达式来搜索和替换标记。

总结下来,正则表达式最核心的能力就是搜索和替换,接下来我们以VS Code环境下搜索和替换中使用的正则表达式为例来学习正则表达式的基本用法,在其他编程语言等环境下正则表达式的用法规则基本大同小异。

由于Vim文本编辑器的用法非常高效,且具有悠久的历史和广泛的用户群,因此我们也同时介绍正则表达式在Vim中的用法。在VS Code环境基础上可以通过安装Vim插件的方式使用Vim。

第一关:基本的字符串搜索方法

在VS Code中跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)的输入框输入字符串即可进行基本的字符串搜索。如下图,左侧搜索面板为跨文件搜索的结果,右侧为文件内搜素的结果。

       b5120b5259459791186d0f04ff7833f2.png      

文件内搜索(Ctrl+F)可以使用Enter键代表继续搜索下一个,Shift+Enter键代表继续搜索上一个。这两个操作在文件内搜索面板上有对应的两个上下箭头,箭头右侧三条横线的小按钮是指在选定内容中查找(Alt+L)。

跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)的输入框内部右侧都有三个小按钮:

  • 第一个选中的话就是搜索时区分大小写(Alt+C);

  • 第二个选中的话表示搜索时全字匹配(Alt+W);

  • 第三个选中的话表示搜索时采用正则表达式(Alt+R),如果输入框中使用了正则表达式的语法规则,则需要选中第三个按钮或使用Alt+R快捷键。显然上图中还没有使用正则表达式。

在 Vim 一般命令模式(Normal Mode)下输入/main(与:底线命令模式相同的方式),即是在当前文档中向光标之下寻找一个名称为 main 的字符串。例如要在档案内搜寻 RegEx 这个字符串,就输入 /RegEx 按回车键即可!在底部的状态栏可以看到输入的搜索命令/RegEx,按回车键之后光标就停在搜索到的下一个 RegEx 字符串上。与之相反,?word 是向光标之上寻找一个字符串名称为 word 的字符串。

按回车键搜索到一个目标字符串之后,这时按 n 这个英文按键,代表重复前一个搜索的动作继续搜索下一个。举例来说, 如果刚刚我们执行 /RegEx 去向下搜寻 RegEx 这个字符串,则按下 n 后,会向下继续搜寻下一个名称为 RegEx 的字符串。如果是执行 ?RegEx 的话,那么按下 n 则会向上继续搜寻名称为 RegEx 的字符串!

按回车键搜索到一个目标字符串之后,这时按 N 这个大写字母英文按键,一般我们用 Shift+n,与 n 刚好相反,为反方向进行前一个搜索动作。 例如 /RegEx 后,按下 N 则表示向上搜寻 RegEx。

使用 /word 配合 n 及 N 是非常有帮助的,可以让你重复的找到一些你希望找到的关键词。


第二关:同时搜索多个字符串的方法

在VS Code跨文件搜索(Ctrl+Shift+F)或文件内搜索(Ctrl+F)时,只要将多个字符串之间增加或运算符“|”,比如"main|int" ,同时选中输入框最右侧使用正则表达式(Alt+R)的小图标,即可同时搜索多个字符串。如下图所示,除了同时搜索多个字符串外,还使用了箭头右侧三条横线的小按钮,即在选定内容区域内查找(Alt+L)多个字符串。

       f81d3e95aa863d7225a8cc19d0929ce7.png      

在 Vim 中搜索多个字符串的用法基本一致。如果你想匹配"yes"或"no",你需要的正则表达式是/yes|no

你也可以搜索超过两种模式,通过添加更多的模式来添加更多的或运算符来分隔它们,如/yes|no|maybe

第三关:在匹配字符串时的大小写问题

到目前为止,你已经看到过正则表达式进行字符串的匹配。但有时,你也可能想要匹配大小写差异。比如大写字母”A","B"和"C",小写字母"a","b"和"c"。

在VS Code跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)中,默认是忽略大小写的,只有通过选中搜索输入框中区分大小写(Alt+C)小按钮,才会按照字符串的大小写严格匹配。

在 Vim 中通过底线命令方式:set ignorecase 设置为忽略大小写;通过:set noignorecase 恢复到大小写敏感的状态,Vim 环境下默认是大小写敏感的。

Unix类的系统默认都是大小写敏感的,而Windows系统下默认是大小写不敏感的。这大概是VS Code和Vim在大小写的默认设置上不同的原因吧。

在 Vim 中也可以通过快捷方式\c 表示大小写不敏感,\C 表示大小写敏感,比如/ignorecase\c,这个正则表达式可以匹配”ignorecase","igNoreCase"和"IgnoreCase"。

注意:有些环境下你可以使用 i 标志匹配来指明是否忽略大小写。你可以通过将 i 标志附加到正则表达式中来使用,使用 i 标志的示例是/ignorecase/i,这个正则表达式可以匹配”ignorecase","igNoreCase"和"IgnoreCase"。

在VS Code跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)中不支持在正则表达式中使用\c这种快捷方式。

第四关:通配符的基本用法

有时不知道模式中的确切字符,就找出所有可能匹配的单词,如果拼写错误会浪费很长时间。幸运的是,可以使用通配符“.”、“+”、“*”、“?”节省时间。

  • 通配符“.”将匹配任意一个字符。通配符也可称为 dot 和 period。你可以像正则表达式中的任何其他字符一样使用通配符。例如,如果你想匹配“hug”,“huh”,“hut”和“hum”,可以使用正则表达式hu.来匹配这所有四个字符串。

  • 通配符“+”用来查找出现一次或多次的字符,例如hahhhhh,可以使用正则表达式hah+来匹配。

  • 通配符“*”匹配零次或多次出现的字符,使用正则表达式hah*来匹配,还可以匹配ha字符串。

  • 通配符“?”指定可能存在的元素,也就是检查前一个元素存在与否,如正则表达式colou?r、favou?rite中通配符“?”前面的u字符存在和不存在两种情况的字符串都会匹配。

简要总结一下通配符“.”表示任意一个字符;“?”表示前一个字符是否存在,也就是存在 0 次或 1 次;“+”表示前一个字符出现一次或多次;“*”表示前一个字符出现 0 次、1 次或多次。

练习题:解释以下几个正则表达式的含义。

  • .?

  • .+

  • .*

“?”表示前一个字符是否存在,也就是存在 0 次或 1 次;“+”表示前一个字符出现一次或多次;“*”表示前一个字符出现 0 次、1 次或多次。

如果是指定只查找某个字符出现3次到5次的情况怎么办呢?可以使用 quantity specifiers 数量说明符指定模式的下限和上限数。数量说明符使用大括号{and}。你将两个数字放在大括号之间用逗号“,”隔开表示上限和下限数。

  • 要匹配字符串"aaah"中出现 3 到 5 次的 a,你的正则表达式将是a{3,5}h;

  • 仅匹配字符串"haaah"与至少出现 3 次的字母 a,正则表达式将是/ha{3,}h;

  • 为了仅匹配"hah"中出现 3 次的字母 a,你的正则表达式将是/ha{3}h。

第五关:匹配具有多种可能性的字符集

你已经学习了如何匹配完整的字符串,如word,以及通配符“.”、“+”、“*”、“?”。这些只是正则表达式的两种极端情况,其中一个查找完全匹配,另一个匹配任意字符的方法。

有这两个极端情况之间的平衡选项,可以使用 character sets 字符集来灵活地搜索文字模式。

  • 用方括号[and]中来定义一组你希望匹配的字符。character sets 字符集允许你通过将其放在方括号[and]中来定义一组你希望匹配的字符。例如,你要匹配"bag","big"和"bug",而不是"bog"。你可以创建正则表达式/b[aiu]g 来执行此操作。[aiu]是只匹配字符"a","i"或"u"的 character sets 字符集。

  • 连字符“-”定义要匹配的字符范围。当你需要匹配一系列字符(例如字母表中的每个字母)时,会需要输入很多字符。幸运的是,有一个内置的功能可以使这个更简短和简单。在 character sets 字符集中,你可以使用连字符“-”定义要匹配的字符范围。例如,要匹配小写字母 a 到 e,你将使用[a-e]。使用连字符“-”匹配一系列字符并不只限于字母,它也可以匹配一系列数字。例如character sets 字符集[0-5]匹配 0 和 5 之间的所有数字,包括 0 和 5。

  • 字符“^”定义不想要匹配的字符,称为negated character sets 否定字符集。要创建一个 否定字符集,你可以在方括号的开括号之后放置一个插入字符“^”。例如[^aeiou]排除元音的所有字符。

如果匹配的可能的字符太多,写起来不是很方便,因而字符集还提供快捷方式的写法。

  • 快捷方式\w 匹配字母数字[A-Za-z0-9_]。这个character sets 字符集匹配大小写字母加数字。注意,这个character sets 字符集还包括下划线字符“_”。

  • 快捷方式\W 搜索\w 的相反方向。需要注意相反的模式使用大写字母。此快捷方式与[^A-Za-z0-9_]相同。

  • 快捷方式\d 搜索数字字符集[0-9]。

  • 快捷方式\D查找非数字字符,等于字符集[^0-9]。

第六关:贪婪匹配 vs. 懒惰匹配

在正则表达式中,greedy 贪婪匹配找到符合正则表达式模式的字符串的最长可能部分,并将其作为匹配返回。相反还有 lazy 懒惰匹配,是找到符合正则表达式模式的字符串的最小可能部分。

你可以将正则表达式t[a-z]*i应用于字符串"titanic"。这个正则表达式基本上是以 t 开始的模式,以 i 结尾,并且之间有0个、1个或多个字母。

正则表达式是默认的是 greedy 贪婪匹配,所以匹配将返回"titani"。它可以找到最大的子字符串,以符合该模式。

但是可以使用?字符将其更改为 lazy 懒惰匹配。“titanic”匹配调整后的t[a-z]*?i正则表达式会返回["ti"]。注意这时字符“?”表示 lazy 懒惰匹配,字符“?”还可以作为通配符表示检查前一个元素存在与否。

练习题:修正正则表达式<.*>以返回 HTML 标签<h1>而不是文本"<h1>Winter is coming</h1>”。记住正则表达式中的通配符“.”可匹配任何一个字符,“.*”可匹配任意多个任意字符。

第七关:一些特殊位置和特殊字符

正则表达式可用于查找匹配字符串开头和末尾位置的模式。

在前面你使用 character sets 字符集中的插入字符“^”创建一[^thingsThatWillNotBeMatched]形式的 negated character set 否定字符集。在方括号之外的正则表达式中插入字符“^”用于表示字符串的开头。美元字符“$”表示字符串的末尾。

  • 插入字符“^”用于表示字符串的开头。

  • 美元字符“$”表示字符串的末尾。

如在"Ricky is first and can be found”查找开头的 Ricky 则为^Ricky,查找结尾的 found 则为/found$。

可以使用\s 搜索空格,这是一个小写的 s 即 space 之意。此模式不仅匹配空格,还包括回车、制表符、换页和新行字符。你可以将其看作与字符集[\r\t\f\n\v]类似。

使用\S 搜索非空格,这是一个大写的 S。此模式将不匹配空格、回车符、制表符、换页和新行字符。你可以想象它类似于字符类[^\r\t\f\n\v]。

  • \n:换行(光标到下行行首);

  • \r:回车(光标到本行行首);

  • \f:换页;

  • \t:水平跳格(水平制表);

  • \v:垂直跳格(垂直制表)。


第八关:使用捕获组复用模式

可能搜索的某些模式在字符串中多次出现,手动重复这些正则表达式是浪费时间的。有一个更好的方法可在你的字符串中有多个重复子串时进行指定,那就是capture groups 捕获组。

用括号(and)可以定义capture groups 捕获组,用于查找重复的子串,即把会重复的模式的正则表达式放在括号内。

要指定重复字符串的出现位置,可以使用反斜杠“\”,然后使用数字。该数字从 1 开始,并随着用括号定义的捕获组数量而增加。比如\1 来匹配前面通过括号定义的第一个捕获组。

使用 capture groups 捕获组来匹配字符串中连续出现三次的数字,每个数字由空格分隔,如(\d+)\s\1\s\1。

第九关:基本的字符串搜索替换方法

在VS Code中基本的字符串搜索替换方法比较简单,只要点击查找输入框左侧的“>”小按钮就可以打开替换输入框,如下图所示。也可以使用快捷键跨文件替换(Ctrl+Shift+H)和文件内替换(Ctrl+H),与跨文件搜索(Ctrl+Shift+F)和文件内搜索(Ctrl+F)相对应。

       19b560b3c68f960d7bf6eb0f2ee0d90d.png      

在 Vim 中基本的字符串搜索替换方法为:n1,n2s/word1/word2/g,以:开头,n1 与 n2 为数字,即在第 n1 与 n2 行之间寻找 word1 这个字符串,并将该字符串取代为 word2 字符串。举例来说,在 100 到 200 行之间搜寻 regex 并取代为 RegEx 则为:100,200s/regex/RegEx/g。

其中 s 是 substitute 的简写,表示执行替换字符串操作;最后的/g 是 global 的简写,表示全局替换。另外与/g 的用法相似,/c 是 comfirm 的简写,表示操作时需要确认;/i 是 ignorecase 的简写,表示不区分大小写。

:1,$s/word1/word2/g 或 :%s/word1/word2/g 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 字符串。

:1,$s/word1/word2/gc 或 :%s/word1/word2/gc 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 字符串,且在取代前显示提示信息给用户确认 (confirm) 是否需要取代。

第十关:复用捕获组的方式进行替换

如果我们在搜索替换中希望保留搜索字符串中的某些字符串作为替换字符串的一部分,可以使用美元符号$访问替换字符串中的捕获组。

比如在搜索正则表达式中的捕获组为(capture groups),则替换的正则表达式中可以直接使用$1复用搜索正则表达式中的捕获组为(capture groups)。

在VS Code中,如果想将项目中所有的HTML标题标签中h改为大写H,搜索正则表达式<h(\d)>可以查找出所有标题标签,如<h1>、<h2>、<h3>、<h4>等,其中还定义了捕获组(\d)。

替换的正则表达式<H$1>使用$1复用了搜索正则表达式中定义的捕获组(\d)。如下图所示。

       276ded1e1e8795d6b75f3b149912b64a.png      

在Vim中,复用捕获组的方式进行替换的用法为:1,$s/(capture groups)/$1/g

如果想在当前文件中将所有的HTML标题标签中h改为大写H则正则表达式为:1,$s/<h(\d)>/<H$1>/g

练习题

1、合理的限制用户名

用户名在互联网上随处可见。它们是用户喜欢的网站给用户一个独特的身份。

你需要检查数据库中的所有用户名。以下是创建用户名时用户必须遵循的一些简单规则。

1)用户名由字母表的字母字符和数字构成。

2)用户名中的字母可以是小写和大写。

3)用户名中的数字必须在末尾,且可以有零个或多个数字。

写出正则表达式以符合上面列出的规则。

参考答案:[A-Za-z]+\d*

2、代码中批量添加和取消注释

在Vim中使用下面命令在指定的行首添加注释。使用命令格式为 :起始行号,结束行号 s/^/注释符/g,注意以冒号开头,如以//为注释符号:10,20s#^#//#g,以#为注释符号:10,20s/^/#/g。

在Vim中使用下面命令取消指定行首的注释,使用的命令格式为 :起始行号,结束行号 s/^注释符//g,注意以冒号开头,如以//为注释符号:10,20s#^//##g,以#为注释符号:10,20s/#//g。

在VS Code中批量添加注释的快捷键为 Ctrl+/和 Ctrl+Shift+A 可以快捷地进行代码注释,Ctrl+/用于单行代码注释和取消注释,Ctrl+Shift+A 用于代码块的注释和取消注释。

本文作者孟宁,未经许可禁止转载!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农孟宁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值