正则表达式基础

简介

正则表达式(Regular Expression,简称 regexregexp)是一种用来匹配和处理文本的模式表示法。它提供了一套强大的搜索、替换和处理文本的工具,用于描述特定的字符序列。

用途:

  • 文本搜索
  • 文本替换
  • 数据验证:如验证电子邮件地址、电话号码、邮政编码等格式是否正确。
  • 数据提取:从日志文件、网页、文档等复杂文本中提取需要的信息。

视频教程

入门
src="https://player.bilibili.com/player.html?isOutside=true\&aid=625512607\&bvid=BV19t4y1y7qP\&cid=187302262\&p=1" data-src="//player.bilibili.com/player.html?isOutside=true&aid=625512607&bvid=BV19t4y1y7qP&cid=187302262&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 710px; height: 392px;"/>

进阶
src="https://player.bilibili.com/player.html?isOutside=true\&aid=625512607\&bvid=BV19t4y1y7qP\&cid=187492466\&p=2" data-src="//player.bilibili.com/player.html?isOutside=true&aid=625512607&bvid=BV19t4y1y7qP&cid=187492466&p=2" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 706px; height: 397px;"/>

复习
src="https://player.bilibili.com/player.html?isOutside=true\&aid=670394789\&bvid=BV1da4y1p7iZ\&cid=260601529\&p=1" data-src="//player.bilibili.com/player.html?isOutside=true&aid=670394789&bvid=BV1da4y1p7iZ&cid=260601529&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 708px; height: 419px;"/>

基础语法

正则表达式由普通字符(字母、数字)和元字符(例如.​、*​等)组成,这些字符和元字符形成了匹配规则。

普通字符

直接匹配字符串,例如文本 /etc/apt/sources.list 内容为:

bash 复制代码
# newer versions of the distribution.
deb http://cn.archive.ubuntu.com/ubuntu/ jammy main restricted
# deb-src http://cn.archive.ubuntu.com/ubuntu/ jammy main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://cn.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
# deb-src http://cn.archive.ubuntu.com/ubuntu/ jammy-updates main restricted

此处忽略几十行

过滤掉注释和空行:

bash 复制代码
cat /etc/apt/sources.list | grep 'deb http'
bash 复制代码
deb http://cn.archive.ubuntu.com/ubuntu/ jammy main restricted
deb http://cn.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
deb http://cn.archive.ubuntu.com/ubuntu/ jammy universe
deb http://cn.archive.ubuntu.com/ubuntu/ jammy-updates universe
deb http://cn.archive.ubuntu.com/ubuntu/ jammy multiverse
deb http://cn.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
deb http://cn.archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted
deb http://security.ubuntu.com/ubuntu/ jammy-security universe
deb http://security.ubuntu.com/ubuntu/ jammy-security multiverse
元字符
元字符 含义 示例
. 匹配除换行符以外的任意单个字符 a.c​ 可以匹配 "abc"、"adc"、"a1c" 等
^ 匹配字符串的开头 ^abc​ 匹配以 "abc" 开头的字符串
​ < / c o d e > < / t d > < t d > 匹配字符串的结尾 < / t d > < t d > < c o d e > a b c 匹配字符串的结尾 abc 匹配字符串的结尾abc​ 匹配以 "abc" 结尾的字符串
* 匹配前面的元素零次或多次 ab*c​ 匹配 "ac"、"abc"、"abbc" 等
+ 匹配前面的元素一次或多次 ab+c​ 匹配 "abc"、"abbc",但不匹配 "ac"
? 匹配前面的元素零次或一次 ab?c​ 匹配 "ac"、"abc"
[] 定义字符类,匹配方括号中任意一个字符 [aeiou]​ 匹配任何一个元音字母 [a-z]​ 匹配所有小写字母
​` `​ 表示"或"关系,匹配两者之一
() 用于分组,影响量词作用范围 (ab)+​ 匹配 "ab"、"abab"、"ababab" 等
\ 用于转义下一个字符,使其失去特殊含义。匹配它们的字面意义。 \.​ 可以匹配句号.​本身(字面) \\​ 可以匹配本身\​本身(字面)
字符类
字符 作用 写法示例
[...] 匹配括号内的任意一个字符 [abc] 匹配 "a"、"b" 或 "c" 中的任意一个字符
[^...] 匹配不在括号内的任意字符 [^abc] 匹配除了 "a"、"b"、"c" 以外的任意字符

过滤掉注释和空行:

bash 复制代码
cat /etc/apt/sources.list | grep -P '^[^#]'

分组语法

符号:使用括号 ()​ 将多个字符或子表达式视为一个整体。

用途:捕获子串、重复匹配、替换部分内容等。

1. 捕获分组

捕获分组将匹配到的内容存储起来,便于后续操作,比如提取子串或替换匹配部分。

语法(pattern)

例如:

regex 复制代码
   (ab)c
  • 这里 (ab) 是一个捕获分组,匹配到 "ab",后面紧跟一个 "c"。匹配结果会将 "ab" 存储为一个组。
示例:提取电话号码中的区号
regex 复制代码
   (\d{3})-(\d{3})-(\d{4})
  • 输入字符串:123-456-7890

  • 捕获分组1:123​ (区号)

  • 捕获分组2:456

  • 捕获分组3:7890

    通过捕获分组,可以很容易地提取到区号或其他部分。

2. 非捕获分组

有时我们只想对表达式进行分组,但不需要捕获其中的内容。这时可以使用非捕获分组

语法(?:pattern)

非捕获分组不会保存匹配的内容,只用于逻辑上的分组或应用操作。

例如:

regex 复制代码
   (?:ab)+
  • 匹配 "ab" 的一次或多次重复,但不会将每次匹配的 "ab" 作为捕获分组存储。

3. 命名捕获分组

有时为了更好地管理分组,尤其是在复杂的正则表达式中,可以为捕获分组指定名称,以便更清晰地引用。

语法(?<name>pattern)

例如:

regex 复制代码
   (?<area_code>\d{3})-(?<prefix>\d{3})-(?<line_number>\d{4})
  • 这段正则表达式捕获电话中的不同部分,并为每个部分指定了名字:area_codeprefixline_number
  • 这样,匹配到的电话号码部分就可以通过名称来引用,而不是通过数字索引。

4. 引用分组

捕获分组在匹配完成后,可以通过反向引用的方式再次使用已经捕获的内容。反向引用通过 \数字​ 来表示,其中 数字​ 是捕获组的编号。

例如:

regex 复制代码
   (\w)\1
  • 这里的 (\w) 捕获了一个单词字符,\1 则引用了这个捕获的字符。因此,它可以匹配两个相同的字符连续出现的情况,比如 "aa" 或 "bb"。
示例:匹配重复的单词
regex 复制代码
   \b(\w+)\b\s+\1\b
  • 匹配两个连续相同的单词,如 hello hello
  • 捕获分组 (\w+) 保存了第一个单词,\1 则引用这个单词,以匹配后续的重复单词。

5. 分组的嵌套

分组可以嵌套使用,一个分组内部可以包含其他分组,匹配到的内容会依次按左括号出现的顺序编号。

例如:

regex 复制代码
   ((\d{3})-(\d{4}))
  • 捕获分组1:(\d{3})-(\d{4}) (整个字符串)
  • 捕获分组2:\d{3} (前三位数字)
  • 捕获分组3:\d{4} (后四位数字)

示例应用:

1. 提取日期

假设我们要提取日期格式为 YYYY-MM-DD​ 的字符串中的年份、月份和日期:

regex 复制代码
   (\d{4})-(\d{2})-(\d{2})
  • 捕获分组1:年份(4位数字)。

  • 捕获分组2:月份(2位数字)。

  • 捕获分组3:日期(2位数字)。

    输入字符串 2024-09-22​,捕获结果为:

  • 分组1:2024

  • 分组2:09

  • 分组3:22

2. 替换文本中的部分内容

假设有一个文本:"My phone number is 123-456-7890"​,我们想用 ***​ 替换中间三位数字:

python 复制代码
   import re
   text = "My phone number is 123-456-7890"
   result = re.sub(r'(\d{3})-(\d{3})-(\d{4})', r'\1-***-\3', text)
   print(result)
   # 输出: My phone number is 123-***-7890

总结

  • 捕获分组用于匹配和存储子串。
  • 非捕获分组用于逻辑上的分组,而不捕获内容。
  • 命名捕获分组通过命名使表达式更加易读。
  • 反向引用允许在正则表达式中重新使用已经捕获的内容。

复用语法

复用规则可以让表达式更简洁。

(1)快捷元符号(基础元符号的简便写法)

元字符 作用
\d 匹配任意数字,相当于 [0-9]
\D 匹配任意非数字字符,相当于 [^0-9]
\w 匹配任意字母、数字或下划线字符,相当于 [a-zA-Z0-9_]
\W 匹配任意非字母、数字或下划线字符,相当于 [^a-zA-Z0-9_]
\s 匹配任意空白字符,包括空格、制表符、换行符等
\S 匹配任意非空白字符
\b 匹配单词边界
\B 匹配非单词边界

(2)量词(量词不是元符号,用来指定前面元素的重复次数。)

字符 作用 写法示例
{n} 匹配前面的元素恰好 n 次 a{2} 匹配 "aa"
{n,} 匹配前面的元素至少 n 次 a{2,} 匹配 "aa"、"aaa" 等
{n,m} 匹配前面的元素至少 n 次,但不超过 m 次 a{2,4} 匹配 "aa"、"aaa" 或 "aaaa"

断言语法

断言本身不匹配字符,它只是定义了一个条件,要求在某个位置满足特定条件才能继续匹配。

  1. 正向先行断言(后面满足条件) :用(?=...)表示,表示在当前位置之后的字符串需要满足括号中的条件才能匹配。
    例如,正则表达式foo(?=bar)会匹配后面紧跟着barfoo
  2. 负向先行断言(后面不满足条件) :用(?!...)表示,表示在当前位置之后的字符串不能满足括号中的条件才能匹配。
    例如,正则表达式foo(?!bar)会匹配后面不是barfoo
  3. 正向后顾断言(前面满足条件) :用(?<=...)表示,表示在当前位置之前的字符串需要满足括号中的条件才能匹配。
    例如,正则表达式(?<=foo)bar会匹配前面紧跟着foobar
  4. 负向后顾断言(前面不满足条件) :用(?<!...)表示,表示在当前位置之前的字符串不能满足括号中的条件才能匹配。
    例如,正则表达式(?<!foo)bar会匹配前面不是foobar

在线练习

sandbox="allow-forms allow-presentation allow-same-origin allow-scripts allow-modals" src="https://codejiaonang.com/" data-src="" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 1169px; height: 655px;"/>

相关推荐
运维小贺6 小时前
Nginx常用的模块
运维·nginx·正则表达式
Viooocc1 天前
正则表达式
正则表达式
vvilkim1 天前
开发中常用的正则表达式规则与应用
正则表达式
林深的林2 天前
正则表达式(1)
正则表达式
ThisIsClark3 天前
【玩转正则表达式】正则表达式常用语法汇总
正则表达式
ThisIsClark3 天前
【玩转正则表达式】替换与正则表达式的结合
正则表达式
浪九天4 天前
Java常用正则表达式(身份证号、邮箱、手机号)格式校验
java·开发语言·正则表达式
ThisIsClark4 天前
【玩转正则表达式】将正则表达式中的分组(group)与替换进行结合使用
数据库·mysql·正则表达式
小张-森林人7 天前
Oracle 字符串分割革命:正则表达式与 Lateral Join 的优雅解法
数据库·oracle·正则表达式
Lojarro7 天前
正则表达式
正则表达式