正则表达式基础与 grep 应用
一、正则表达式是什么
经典的数据匹配查询技术, 内部使用贪心算法完成对数据集快速的模式查询,
相比传统的字符串处理str函数, 正则表达式的效率更高, 匹配速度更快, 而且支持模糊查询,真正意义上str相关函数不算是数据匹配技术
正则技术的核心是数据匹配, 但是功能还是很多样的
二、正则表达式的使用
-
先分析待处理数据的规律与特征
-
根据规律编写正则语句
-
正则语句由基础表达式和符号表达式组成
- 基础表达式:普通字符,如
a、hello、张三
- 符号表达式:由具有特殊含义的元字符组成
- 基础表达式:普通字符,如
-
使用正则表达式逐项检查待匹配数据。
-
符合规则即匹配成功,输出或保留结果;不符合规则则继续检查后续数据。
三、使用正则技术的两种方式
在命令中使用
grep '正则字符串/语句' Filename从 Filename 中读取数据,按照给定表达式进行匹配并显示符合规则的行
2. 在代码中使用
程序可以调用支持正则表达式的函数完成匹配。本节主要讲解正则语法和命令行演示,代码中的正则函数将在后续内容中继续使用。
四、正则元字符
正则表达式中的一些符号与普通字符外形相同,但含义完全不同。正则表达式默认以一个字符为基本匹配单位。
转义符 \
正则元字符较多,当希望特殊符号按正则含义工作,或希望取消它的特殊含义时,需要根据当前正则语法进行转义
星号 *
以前一个表达式为参照,表示前面的表达式连续出现 0 次或多次
grep 'aa*' test.txt该表达式先匹配一个 a,后面的 a* 可以继续匹配 0 个或多个 a
如果只是查找普通字符,却给它添加次数范围,可能会产生更多次匹配,降低效率
加号 +
以前一个表达式为参照,表示前面的表达式连续出现 1 次或多次。
grep 的基本正则表达式写法需要转义:
grep 'a\+' test.txt它与 a* 的主要区别是:a* 允许出现 0 次,a\+ 至少出现 1 次。
点号 .
表示任意一个字符
每个 . 只占一个字符的匹配位置;换行、缩进不属于普通的一行内字符匹配
行首 ^ 与行尾 $
^:以后面的表达式为参照,要求它位于行首。$:以前面的表达式为参照,要求它位于行尾。^$:行首后立即到行尾,中间没有字符,因此用来匹配空行。
查看空行所在的行号
grep -n '^$' test.txt过滤空行并把结果写入新文件
grep -v '^$' test.txt > newfilecat newfile其中:
-n显示匹配结果的行号-v反向选择,即输出不符合表达式的行>将结果重定向到文件
字符集合 []
每次匹配时,从集合中选择一个字符进行匹配,最小匹配粒度仍然是一个字符
示例
aoodboodcoodabdooodgrep '[a|b|d]ood' test.txt常见范围写法:
[a-z]:小写字母[A-Z]:大写字母[0-9]:数字[a-zA-Z0-9]:大小写字母或数字[^表达式]:集合取非,匹配集合中未列出的任意一个字符
分组 ()
用于创建一个表达式,将多个字符组合成一个整体,提高表达式的匹配粒度
圆括号需要转义
grep '\(description\)\*' file这里把 description 当作一个整体,再由后面的次数符号控制整个分组的出现次数
次数限定 {}
{} 以前一个表达式为参照,用于限定连续出现的次数。需要转义
a\{n\}:a恰好连续出现n次。a\{n,\}:a至少连续出现n次。a\{n,m\}:a连续出现n到m次。
课堂演示:
grep 'a\{2\}' test.txtgrep 'a\{2,5\}' test.txt问号 ?
? 跟在 + 或 * 后面时,可用于切换匹配模式,在贪婪模式和非贪婪模式之间进行选择
是否需要转义取决于所使用的正则语法和工具
五、手机号匹配示例
课堂给出的手机号规则:
- 一共由 11 位数字组成。
- 第一位固定为
1。 - 第二位是
3到9之间的任意数字。 - 后九位是
0到9之间的任意数字。 - 必须整行符合规则,不能在更长的字符串中只截取其中 11 位。
课堂测试数据:
182045085001378890557111078321331192667831323115589078781最终表达式:
grep '^1[3-9][0-9]\{9\}$' file六、贪心匹配
正则匹配会尽可能多地获取符合条件的内容
追求当前步骤的局部最优,但不一定得到整体最优
贪心过程具有向前推进的特点,前面的选择出现问题后,不一定能回到任意位置重新选择
示例
<div>内容A</div>垃圾数据A<div>内容B</div>垃圾数据B<div>内容C</div>如果表达式范围过宽,可能从第一个 <div> 一直匹配到最后一个 </div>
处理思路是缩小字符范围,例如用“不是 < 的字符”限制标签之间的正文
<div>[^<]+?</div>表达式的范围必须尽量精确,否则贪心匹配可能得到超过预期的结果
如果这篇文章对你有帮助,欢迎分享给更多人!





