正则表达式基础
侧边栏壁纸
  • 累计撰写 146 篇文章
  • 累计收到 2 条评论

正则表达式基础

soulio
2024-09-22 / 0 评论 / 9 阅读 / 正在检测是否收录...

简介

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

用途:

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

视频教程

入门

进阶

复习

基础语法

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

普通字符

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


# 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

此处忽略几十行

过滤掉注释和空行:

cat /etc/apt/sources.list | grep 'deb http'
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" 开头的字符串
$ 匹配字符串的结尾 abc$​ 匹配以 "abc" 结尾的字符串
* 匹配前面的元素零次或多次 ab*c​ 匹配 "ac"、"abc"、"abbc" 等
+ 匹配前面的元素一次或多次 ab+c​ 匹配 "abc"、"abbc",但不匹配 "ac"
? 匹配前面的元素零次或一次 ab?c​ 匹配 "ac"、"abc"
[] 定义字符类,匹配方括号中任意一个字符 [aeiou]​ 匹配任何一个元音字母
[a-z]​ 匹配所有小写字母
| 表示“或”关系,匹配两者之一
http|https​ 匹配 "http"、"https"
() 用于分组,影响量词作用范围 (ab)+​ 匹配 "ab"、"abab"、"ababab" 等
\ 用于转义下一个字符,使其失去特殊含义。匹配它们的字面意义。
\.​ 可以匹配句号.​本身(字面)
\\​ 可以匹配本身\​本身(字面)

字符类

字符 作用 写法示例
[...] 匹配括号内的任意一个字符 [abc] 匹配 "a"、"b" 或 "c" 中的任意一个字符
[^...] 匹配不在括号内的任意字符 [^abc] 匹配除了 "a"、"b"、"c" 以外的任意字符

过滤掉注释和空行:

cat /etc/apt/sources.list | grep -P '^[^#]'

分组语法

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

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

1. 捕获分组

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

语法(pattern)

例如:

   (ab)c
  • 这里 (ab)​ 是一个捕获分组,匹配到 "ab",后面紧跟一个 "c"。匹配结果会将 "ab" 存储为一个组。

示例:提取电话号码中的区号

   (\d{3})-(\d{3})-(\d{4})
  • 输入字符串:123-456-7890

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

  • 捕获分组2:456

  • 捕获分组3:7890

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

2. 非捕获分组

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

语法(?:pattern)

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

例如:

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

3. 命名捕获分组

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

语法(?<name>pattern)

例如:

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

4. 引用分组

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

例如:

   (\w)\1
  • 这里的 (\w)​ 捕获了一个单词字符,\1​ 则引用了这个捕获的字符。因此,它可以匹配两个相同的字符连续出现的情况,比如 "aa" 或 "bb"。

示例:匹配重复的单词

   \b(\w+)\b\s+\1\b
  • 匹配两个连续相同的单词,如 hello hello​。
  • 捕获分组 (\w+)​ 保存了第一个单词,\1​ 则引用这个单词,以匹配后续的重复单词。

5. 分组的嵌套

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

例如:

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

示例应用:

1. 提取日期

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

   (\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"​,我们想用 ***​ 替换中间三位数字:

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

在线练习

本文共 1799 个字数,平均阅读时长 ≈ 5分钟
0

海报

正在生成.....

评论 (0)

取消