news 2026/4/23 13:30:21

【RegExp】正则表达式 - 基础语法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【RegExp】正则表达式 - 基础语法

正则表达式基础

  • 简介
    • 在线工具
  • 元字符
  • 分组与引用
  • 运算符优先级
  • 贪婪模式

简介


在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard),也就是*?。如果你想查找某个目录下的所有的Word文档的话,你会搜索*.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂。


假设你在一篇英文小说里查找 hi,你可以使用正则表达式hi

这几乎是最简单的正则表达式了,它可以精确匹配这样的字符串:由两个字符组成,前一个字符是 h,后一个是 i。通常,处理正则表达式的工具会提供一个忽略大小写的选项,如果选中了这个选项,它可以匹配 hi,HI,Hi,hI 这四种情况中的任意一种。

不幸的是,很多单词里包含hi这两个连续的字符,比如 him,history,high 等等。用hi来查找的话,这里边的 hi 也会被找出来。如果要精确地查找 hi 这个单词的话,我们应该使用\bhi\b

\b是正则表达式规定的一个特殊代码(将其称之为元字符),代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。

假如你要找的是hi后面不远处跟着一个Lucy,你应该用\bhi\b.*\bLucy\b

这里,.是另一个元字符,匹配除了换行符以外的任意字符。*同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定*前边的内容可以连续重复使用任意次以使整个表达式得到匹配。

因此,.*连在一起就意味着任意数量的不包含换行的字符。现在\bhi\b.*\bLucy\b的意思就很明显了:先是一个单词 hi,然后是任意个任意字符(但不能是换行),最后是 Lucy 这个单词。


如果同时使用其它元字符,我们就能构造出功能更强大的正则表达式。比如下面这个例子:

0\d\d-\d\d\d\d\d\d\d\d匹配这样的字符串:以 0 开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。

这里的\d是个新的元字符,匹配一位数字(0,或1,或2,或……)。-不是元字符,只匹配它本身——连字符(或者减号,或者中横线,或者随你怎么称呼它)。

为了避免那么多烦人的重复,我们也可以这样写这个表达式:0\d{2}-\d{8}。这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配 2 次(8次)。


总的来说,正则表达式一种特殊的编程语言,专门用来匹配一些特定的字符串。正则表达式一般不会单独使用,通常会结合具体的编程语言(例如 C++、Python、Perl等)或者工具(vim等)使用。


在线工具


正则表达式本身比较复杂,可以借助一些工具来验证所写的正则表达式是否符合预期。

  • Regulex - JavaScript Regular Expression Visualizer.

元字符


基本元字符

MetacharacterDescriptionsExamples
\转义字符,使后面的字符失去特殊含义或者标记为特殊字符\.匹配实际的点号而不是任意字符,\n匹配一个换行符
^匹配字符串的开始位置^abc匹配以 abc 开头的字符串
$匹配字符串的结束位置xyz$匹配以 “xyz” 结尾的字符串
.匹配除换行符(\n)外的任意单个字符a.b匹配 “aab”, “a1b”, “a b” 等
*匹配前面的子表达式零次或多次zo*能匹配 “z” 以及 “zoo”
+匹配前面的子表达式 1 次或多次zo+能匹配 “zo” 以及 “zoo”,但不能匹配 “z”
?匹配前面的子表达式零次或一次do(es)?可以匹配 “do” 或 “does”
{n}n 是一个非负整数。匹配确定的 n 次o{2}不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o
{n,}n 是一个非负整数。至少匹配n 次o{2,}不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次o{1,3}匹配 “fooooood” 中的前三个 o
x|y匹配 x 或 yz|food能匹配 “z” 或 “food”
[xyz]字符集合。匹配所包含的任意一个字符[abc]可以匹配 “plain” 中的 ‘a’。
[^xyz]负值字符集合。匹配未包含的任意字符[^abc]可以匹配 “plain” 中的’p’、‘l’、‘i’、‘n’
[a-z]字符范围。匹配指定范围内的任意字符[a-z]可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符[^a-z]可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符
\b匹配一个单词边界,也就是指单词和空格间的位置er\b可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’
\B匹配非单词边界er\B能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’
\cx匹配由 x 指明的控制字符,x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符\cM匹配一个 Control-M 或回车符
\d匹配一个数字字符等价于[0-9]
\D匹配一个非数字字符等价于[^0-9]
\f匹配一个换页符等价于\x0c\cL
\n匹配一个换行符等价于\x0a\cJ
\r匹配一个回车符等价于\x0d\cM
\s匹配任何空白字符,包括空格、制表符、换页符等等等价于[ \f\n\r\t\v]
\S匹配任何非空白字符等价于[^ \f\n\r\t\v]
\t匹配一个制表符等价于\x09\cI
\v匹配一个垂直制表符等价于\x0b\cK
\w匹配字母、数字、下划线等价于[A-Za-z0-9_]
\W匹配非字母、数字、下划线等价于[^A-Za-z0-9_]

分组与引用


直接在字符后面加上限定符,就可以实现重复单个字符。如果想要重复多个字符,比如重复 ab,可以使用小括号来指定子表达式(也叫做分组),然后指定这个子表达式的重复次数。

例如,(ab)+可以匹配 “ab”、“abab”、“ababab” 等,但不能匹配 “a” 或 “b”。

  • 捕获分组

正则表达式中有几种不同类型的分组,捕获分组是最常见的分组形式,它会捕获匹配的内容并分配一个编号(从 1 开始)。后续可以基于编号访问分组中的内容。

示例:

(\d{4})-(\d{2})-(\d{2})# 匹配日期格式 YYYY-MM-DD

这个表达式会创建3个分组:① 4位数字的年份;② 2位数字的月份;③ 2位数字的日期

  • 分组引用

分组最强大的功能之一是可以在正则表达式内部或外部引用已匹配的内容。

在正则表达式内部引用前面的分组,使用\num,其中 num 是分组索引。

(\w+)\1# 匹配重复的单词,如 "hello hello"

这个 pattern 会匹配两个相同的单词,中间用空格分隔,其中\1就是对分组的引用。

  • 非捕获分组

使用(?:pattern)语法,表示只分组但不捕获。

例如,(?:Mr|Ms|Mrs)\. (\w+)表示匹配 “Mr. Smith” 但只捕获 “Smith”。

  • 命名分组与引用

在一些高级语言中,还可以为分组指定名称,提高可读性(不同语言语法可能不同)。

例如,在 Python 中对分组进行命令的方法如下:

### Named Capturing Group(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})### Reference(?P<word>\w+)(?P=word)

运算符优先级


正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。

相同优先级的从左到右进行运算,不同优先级的运算先高后低。

正则表达式中,各种运算符的优先级顺序如下:

优先级运算符描述
1\转义符
2()、[]圆括号和方括号
3*、 +、 ?、 {n}、{n,}、{n,m}限定符
4^、$、\任何元字符、任何字符定位点和序列(即:位置和顺序)
5|"或"操作

贪婪模式


当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以表达式a.*b为例,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个?

这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于 aabab 的话,它会匹配 aab(第一到第三个字符)和ab(第四到第五个字符)。

为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权。

对于其他的的重复限定符,都支持使用?进入懒惰模式:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/7 11:49:49

Anthropic宪法

Anthropic宪法参考网址 ConstitutionalAI(RLAIF)_通过AI自我监督实现无害化训练&#xff1a;https://blog.csdn.net/shizheng_Li/article/details/147634853Claude3秘密武器曝光_Claude宪法&#xff1a;https://cloud.tencent.com/developer/article/2419721Constitutional AI …

作者头像 李华
网站建设 2026/4/23 10:44:20

太平洋大西洋水流问题:DFS递归、DFS栈、BFS三种解法全解析

一、问题描述给定一个 m x n 的非负整数矩阵 heights &#xff0c;矩阵的左边界和上边界毗邻太平洋&#xff0c;右边界和下边界毗邻大西洋。水流的流动规则为&#xff1a;只能从高处流向低处&#xff0c;或者在同等高度的单元格之间流动。请找出矩阵中所有既可以流向太平洋&…

作者头像 李华
网站建设 2026/4/23 13:28:52

【文献速递】split-TurboID如何绘制细胞器“联络图”?

在细胞这个拥挤而有序的微观世界里&#xff0c;蛋白质与蛋白质之间的相互作用&#xff0c;往往决定着生命的运行逻辑。然而&#xff0c;这些“分子密谈”往往转瞬即逝&#xff0c;难以捕捉。近年来&#xff0c;临近标记技术的兴起为我们打开了一扇窗&#xff0c;而其中split-Tu…

作者头像 李华
网站建设 2026/4/18 7:46:03

《深入浅出python机器学习》读书笔记(四)

《深入浅出python机器学习》读书笔记&#xff08;四&#xff09; 第四章 广义线性模型 文章目录《深入浅出python机器学习》读书笔记&#xff08;四&#xff09;前言一、线性回归模型线性回归模型的基础示例使用线性回归预测糖尿病数据集模型评估要点&#xff1a;二、岭回归—…

作者头像 李华
网站建设 2026/4/23 12:10:19

测试自动化在微服务架构中的应用:策略、挑战与演进

微服务时代的测试范式转变随着企业数字化转型的深入&#xff0c;微服务架构已成为现代软件系统的主流设计模式。相较于传统的单体架构&#xff0c;微服务通过将应用拆分为一组小而自治的服务&#xff0c;带来了开发敏捷性、技术多样性和可扩展性等优势。然而&#xff0c;这种架…

作者头像 李华