Skip to main content

正则(regex)

正则语法

量词(Quantifiers)

在正则表达式中,*+ 都是量词(Quantifiers),它们决定了前面的字符或分组可以重复出现的次数。

它们的核心区别在于:“是否允许出现 0 次”

符号名称匹配次数是否必选含义
*星号 (Asterisk)0 次或多次可选前面的内容可有可无,有的话可以有很多个。
+加号 (Plus)1 次或多次必选前面的内容至少要出现一次,也可以有很多个。

如果想限制具体的次数,可以使用大括号:

  • {n}:正好出现n次。
  • {n,}:至少出现n次。
  • {n,m}:出现n到m次。

此外,?跟在前面的字符后代表可有可无。

等价符号

.匹配除换行符(\n、\r)之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像"(.|\n)"的模式。
\d匹配一个数字字符。等价于 [0-9]。
\D匹配一个非数字字符。等价于 [ ^0-9]。
\w匹配一个字母、数字、下划线。等价于[A-Za-z0-9_]。
\W匹配非(字母、数字、下划线)。等价于 [ ^A-Za-z0-9_]。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于 [ ^ \f\n\r\t\v]。
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM。
\t匹配一个制表符。等价于 \x09 和 \cI。

贪婪匹配与懒惰匹配

简单来说,**贪婪匹配(Greedy)懒惰匹配(Lazy/Non-greedy)**的区别在于:面对多个可能的匹配结果时,是“能拿多少拿多少”还是“够了就行”。在正则表达式中,这两种模式直接影响你抓取数据的范围。

1. 贪婪匹配 (Greedy)

这是正则表达式的默认模式

  • 行为: 匹配器会尽可能多地吞掉字符,直到不符合条件为止。
  • 常用符号: *(0或多个)、+(1或多个)、{n,}
  • 例子: 假设我们要匹配 <div>内容1</div><div>内容2</div> 中的 HTML 标签。
    • 正则: <div>.*</div>
    • 匹配结果: <div>内容1</div><div>内容2</div>
    • 解析: 它没有在第一个 </div> 停止,而是直接匹配到了文档的最后一个 </div>

2. 懒惰匹配 (Lazy / Non-greedy)

  • 行为: 匹配器在满足条件的前提下,尽可能少地匹配字符。一旦找到匹配项,立即停止。
  • 实现方式: 在贪婪量词后面加一个问号 ?
  • 常用符号: *?+???{n,}?
  • 例子: 同样的 HTML 字符串。
    • 正则: <div>.*?</div>
    • 匹配结果: <div>内容1</div> (以及接下来的 <div>内容2</div>
    • 解析: 碰到第一个符合条件的 </div> 它就“收手”了。

核心区别对比

特性贪婪匹配 (Greedy)懒惰匹配 (Lazy)
性格贪心,全都要知足,够了就好
匹配长度匹配最长的字符串匹配最短的字符串
控制符*, +, {n,}*?, +?, {n,}?
回溯机制从后往前找(先吞下全部再吐出来)从前往后找(吃一点看一点)

举个直观的例子

字符串:"apple" "banana" "cherry"

  • 贪婪模式 ".*":匹配结果是整个字符串 "apple" "banana" "cherry"。它认为最开头的 " 和最末尾的 " 才是这一对。
  • 懒惰模式 ".*?":匹配结果是三个独立的项:"apple""banana""cherry"

特殊字符

**^:**匹配搜索字符串开始的位置。 如果标志中包括 m(多行搜索)字符,^ 还将匹配 \n 或 \r 后面的位置。

**$:**匹配搜索字符串结尾的位置。 如果标志中包括 m(多行搜索)字符,^ 还将匹配 \n 或 \r 前面的位置。

正则表达式 ^.{2,100}$ 匹配的是 任意长度在 2 到 100 个字符之间的字符串。

编程语言中的正则实现