正则表达式(Regex)教程

正则表达式(Regular Expression,简称 regex)是一个强大的文本处理工具,用于在字符串中进行模式匹配、查找和替换。正则表达式被广泛应用于编程、数据分析、日志处理、网络爬虫等领域。

目录

  1. 正则表达式基础语法
  2. 常用正则表达式示例
  3. 正则表达式的高级用法
  4. 正则表达式的常见错误
  5. 相关实践示例

正则表达式基础语法

1. 字符匹配

  • .: 匹配任意单个字符(除了换行符)。
  • \d: 匹配数字,等价于 [0-9]
  • \D: 匹配非数字,等价于 [^0-9]
  • \w: 匹配字母、数字和下划线,等价于 [a-zA-Z0-9_]
  • \W: 匹配非字母、非数字、非下划线字符,等价于 [^a-zA-Z0-9_]
  • \s: 匹配任意空白字符(包括空格、制表符、换行符等)。
  • \S: 匹配非空白字符。

2. 字符集(Character Set)

  • [abc]: 匹配 abc 中的任意一个字符。
  • [^abc]: 匹配除了 abc 外的任意字符。
  • [a-z]: 匹配任意小写字母。
  • [A-Z]: 匹配任意大写字母。
  • [0-9]: 匹配任意数字。

3. 量词(Quantifiers)

  • *: 匹配前面的子表达式 0 次或多次。
  • +: 匹配前面的子表达式 1 次或多次。
  • ?: 匹配前面的子表达式 0 次或 1 次。
  • {n}: 匹配前面的子表达式恰好 n 次。
  • {n,}: 匹配前面的子表达式至少 n 次。
  • {n,m}: 匹配前面的子表达式至少 n 次,最多 m 次。

4. 边界匹配

  • ^: 匹配输入字符串的开始。
  • $: 匹配输入字符串的结束。
  • \b: 匹配单词的边界(字母、数字和下划线的边界)。
  • \B: 匹配非单词边界。

5. 分组和选择

  • (): 用于分组,把多个字符或表达式组合成一个单元。例如 (abc) 可以匹配字符串 “abc”。
  • |: 或运算符,匹配 | 两边的任意一个表达式。例如 abc|def 可以匹配 “abc” 或 “def”。

6. 反向引用

  • \1, \2, \3, …: 引用前面括号内的分组。\1 匹配第一个分组的内容,\2 匹配第二个分组的内容,依此类推。

7. 预定义字符集

  • \b: 单词边界。
  • \B: 非单词边界。
  • \A: 匹配字符串的开始。
  • \Z: 匹配字符串的结束。
  • \z: 匹配字符串的结束(忽略换行符)。

c常用正则表达式示例

1. 邮箱地址匹配

正则表达式: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

解释:

  • ^[a-zA-Z0-9._%+-]+: 匹配邮箱的用户名部分(字母、数字和一些符号)。
  • @: 匹配 “@” 符号。
  • [a-zA-Z0-9.-]+: 匹配邮箱的域名部分(字母、数字、点、连字符)。
  • \.[a-zA-Z]{2,}$: 匹配域名后缀(至少两个字母)。

2. 手机号匹配

正则表达式: ^1[3-9]\d{9}$

解释:

  • ^1: 匹配以 1 开头。
  • [3-9]: 第二位数字为 3 到 9 之间的任意一个。
  • \d{9}$: 后面跟着 9 个数字。

3. 日期格式匹配(如 YYYY-MM-DD)

正则表达式: ^\d{4}-\d{2}-\d{2}$

解释:

  • c^\d{4}: 匹配 4 个数字(年份)。
  • -\d{2}: 匹配一个 “-” 后面跟着 2 个数字(月份)。
  • -\d{2}$: 匹配一个 “-” 后面跟着 2 个数字(日期)。

正则表达式的高级用法

1. 懒惰匹配(Lazy Matching)

默认情况下,量词(如 *+)是贪婪的,即它们尽可能多地匹配字符。懒惰匹配会让它们尽可能少地匹配字符。

  • .*?: 匹配任意字符(最少匹配)。
  • .+?: 匹配至少一个字符(最少匹配)。

2. 断言(Assertions)

断言用来匹配某个位置,而不消耗字符。

  • 正向先行断言(Positive Lookahead):(?=...)。表示当前位置后面必须满足某个条件。
  • 负向先行断言(Negative Lookahead):(?!...)。表示当前位置后面不能满足某个条件。

3. 替换与分割

  • 替换: 使用 replace 函数可以替换字符串中匹配的部分。例如,在 Python 中可以使用 re.sub() 来进行替换。
  • 分割: 使用 split 函数根据正则表达式分割字符串。例如,在 Python 中使用 re.split()

正则表达式的常见错误

1. 忘记转义特殊字符

在正则表达式中,某些字符(如 ., *, ?, +, (, ), [, ], \\ 等)有特殊含义。如果要匹配这些字符本身,必须使用反斜杠进行转义(例如:\.)。

2. 贪婪匹配导致问题

正则表达式的量词默认是贪婪的,会匹配尽可能多的字符,可能导致不想要的结果。可以使用懒惰匹配来限制匹配的字符数。

3. 不考虑行结束符(如换行符)

默认情况下,正则表达式的 . 不匹配换行符。如果想要匹配所有字符,包括换行符,可以使用 re.DOTALL 标志(在 Python 中)。


相关实践示例

1. 行匹配中忽略出现或者不出现的关键字

例如有些日志行 以 三种开头,但是经过沟通发现 真实数据格式 是以 开头,然后 结束,但是 会抛出Java异常类。

具体日志格式为

1
2
3
4
5
6
7
8
9
<pattern>2025-02-10 xxxx
</pattern><pattern>2025-02-10 xxxx
</pattern><pattern>2025-02-10 xxxx
<mesgid></msgid>
</pattern>
<pattern>2025-02-10 xxxx
</pattern> xxxx
xxxxxxx
xxxxxx

真实的数据行结构分别为下面四种,

1
2
<pattern>2025-02-10 xxxx
</pattern>
1
2
          <pattern>2025-02-10 xxxx
</pattern>
1
2
3
          <pattern>2025-02-10 xxxx
<mesgid></msgid>
</pattern>
1
2
3
4
<pattern>2025-02-10 xxxx
</pattern> xxxx
xxxxxxx
xxxxxx

如果通过正则识别将下面的四种数据分开,

正常正则的正则识别规则

1
^(?:</pattern>)?<pattern>

日志采集系统正则识别规则

1
\n((?:</pattern>)?<pattern>)