PCRE Lookaround (零宽断言)总结(R & Python 通用)

首先 记住一个要点:出现<就看左边,没有<就是看右边。?=引入"断言",我们的目标是提取"断言"前或者后方的字符

0️⃣ 示例:从句子中提取最后一个价格

r 复制代码
text="The prices are $120, $45 and $300 today."

使用str_extract_all(text,pattern = "\\d+")能提取所有数字,但是要提取最后一个价格 $300,如何只提取满足特定条件(如在 $ 后面、或者,前面)?

这就需要 PCRE 的 lookaround(零宽断言) 技巧,R和Python基本通用。

1,2节为PCRE简介,可以跳过阅读


1️⃣ PCRE 简介

PCRE = Perl Compatible Regular Expressions(Perl 兼容正则表达式)

  • 不是语言,而是 正则表达式引擎规则
    • 支持特殊符号、分组、反向引用、lookaround 等高级功能
    • 控制字符串匹配方式
  • 可理解为:"正则表达式的标准语法"
是否使用 PCRE 语言/工具
✔ 使用 R 的 stringr/stringi
✔ 使用 PHP(preg 系列)
✔ 使用 VSCode、grep -P
✘ 不使用 PCRE(类似) Python re(独立实现,但语法 90% 接近)
✘ 不使用 PCRE JavaScript 正则(ECMA262 标准)

2️⃣ R 与 Python 正则对比

2.1 提取匹配函数

功能 R:stringr Python:re
单个匹配 str_extract() re.search().group()
全部匹配 str_extract_all() re.findall()
是否 PCRE 风格 ✔(语法基本一致)

关键差异

  • R 字符串中 \ 需写成 \\
  • Python 原生字符串 r"" 可直接写 \

学会一次,R/Python 都可用。


3️⃣ lookaround 四种零宽断言

3.1 四种写法与记忆规律

类型 英文名称 语法 描述说明
正向前瞻 Lookahead XXXXX(?=...) 检查当前位置右边 是否满足条件,提取前面的字符
正向后顾 Lookbehind (?<=...)XXXXX 检查当前位置左边 是否满足条件,提取后面的字符
负向前瞻 Negative Lookahead XXXXX(?!...) 检查右边不满足条件
负向后顾 Negative Lookbehind (?<!...)XXXXX 检查左边不满足条件

规律总结

  • ?:引入断言
  • =:等于 (满足条件)
  • !:非 (不满足条件)
  • <:左边(后顾),没有 < 则默认右边(前瞻)

4️⃣ lookaround 基本示例

示例句子

text 复制代码
"The prices are $120, $45 and $300 today."

4.1 提取 $ 后所有数字(正向后顾,Lookbehind)

r 复制代码
stringr::str_extract_all(text, "(?<=and\\s\\$)\\d+")
python 复制代码
re.findall(r"(?<=and\s\$)\d+", text)

输出['300']

看是 "and空格$" ,则提取后方的数字


4.2 提取非 $ 后数字(负向后顾, Neg Lookbehind)

r 复制代码
str_extract_all(text, "(?<!\\$)\\d+")
python 复制代码
re.findall(r"(?<!\$)\d+", text)

输出['20', '5', '00']

看不是$,则提取后方的数字。


4.3 正向前瞻 (?=...) (Lookahead)

r 复制代码
str_extract_all(text, "\\d+(?=\\s)")
python 复制代码
re.findall(r"\d+(?=\s)", text)

输出['45', '300']

向右看是空格,则提取前方的数字。


4.4 负向前瞻 (?!...) (Neg Lookahead)

r 复制代码
str_extract_all(text, "\\d+(?![\\s,])")
python 复制代码
re.findall(r"\d+(?![\s,])", text)

输出['12', '4', '30']

向右看不是空格也不是逗号,取其前方的数字


5️⃣ R 中使用 PCRE 注意事项

  • base R 函数(grep, gsub, sub, grepl)默认不支持 lookaround
  • 使用 PCRE 扩展语法需加 perl=TRUE
使用方式 是否需要 perl=TRUE 引擎
base R POSIX → PCRE
stringr/stringi ICU(支持)

6️⃣ 实战示例集合

注意!R语言中是双斜杠进行转义

任务 示例文本 正则 输出示例
提取 email @ 前用户名 "Contact us at alice@example.com or bob.smith@domain.org." [^\\s@]+(?=@) ['alice','bob.smith']
基因名后数字 "Gene expression: TP53_123, BRCA1_45, MYC_300." (?<=_)[0-9]+ ['123','45','300']
提取 $ 后数字(保留小数点) "Prices: $199, $20.5, 30.0 USD." (?<=\\$)\d+(?:\\.\\d+)? ["199","20.5]"
提取 URL 最后文件名 "URLs: http://example.com/data/file.txt and https://site.org/index.html" (?<=/)[^/]+$ ['index.html']
提取 hashtags "Hashtags: #fun #learning #RStats" (?<=#)\w+ ['fun','learning','RStats']
排除 $ / 括号 / 基因编号 "Mixed: $100, 200, (300), geneX_500, email@test.com" (?<!\$)(?<!\()\b\d+\b ['200']

\b和\w详见 附录:单词边界 的介绍


🔹 总结

  1. 四种 lookaround 的记忆规律:
    • ?=:右边等于 → 正向前瞻
    • ?<=:左边等于 → 正向后顾
    • ?!:右边非 → 负向前瞻
    • ?<!:左边非 → 负向后顾
    • 不用管什么正负前后,只要<就是在左边,没有<就是在右边
  2. R/Python 正则基本一致,R 注意 \\ 转义
  3. lookaround 零宽,匹配位置不消耗字符,可精确控制条件。
  4. **注意!**R语言中 PCRE lookbehind 的长度必须可预估 ,不能将 .*这种任意长度的模式放在结构中,如(?<!\(\.*)\d+(?!\.*\))会报错。Python的regex模块支持可变长度。

附录:单词边界


1️⃣ 单词字符 \w

  • 匹配 字母、数字或下划线 [A-Za-z0-9_]

2️⃣ 单词边界 \b

  • 位置,不是字符
  • 匹配单词开始或单词结束的位置
  • 条件:左右一边是单词字符,一边是非单词字符或字符串开头/结尾

3️⃣ 示例:"abc 123 _500 $45"

标注 | 表示字符间的位置:

复制代码
|a|b|c| |1|2|3| | _ |5|0|0| |$|4|5|
  • "abc"
    • |a ✅ 左边非单词字符(开头) → 边界
    • c| ✅ 右边空格 → 边界
    • b|c ❌ 两边都是单词字符 → 不是边界
  • "123"
    • |1 ✅ 左边空格 → 边界
    • 3| ✅ 右边空格 → 边界
  • "_500"
    • _ |5 ❌ 左边 _ 是单词字符 → 不是边界
    • 5| ❌ 右边 0 是单词字符 → 不是边界
  • "$45"
    • $|4 ✅ 左边 $ 非单词字符 → 边界
    • 5| ✅ 右边空格 → 边界

4️⃣ 总结

  • \w → 单词字符(字母/数字/下划线)
  • \b → 单词边界(单词开始或结束位置)
  • \b\d+\b → 只匹配独立数字 ,即两边均是单词边界的多个数值,不会匹配 abc,_500$45,而是123,50045
相关推荐
任子菲阳1 小时前
学Java第五十二天——IO流(下)
java·开发语言·intellij-idea
core5121 小时前
Google A2A (Agent-to-Agent) 协议实战 —— 用 Python 构建“智能体互联网”
python·agent·a2a
zoujiahui_20181 小时前
使用venv命令创建和使用python环境
开发语言·python
666HZ6661 小时前
C语言——putchar 与 getchar
c语言·开发语言
资深低代码开发平台专家1 小时前
Python自动化:一键搞定“文件批量重命名”
python
追光天使1 小时前
Python的后端框架
python
姚华军1 小时前
利用Python算法,解析PDF文件并生成文档分块Chunks,追加到RagFlow知识库
开发语言·python·pdf·chunks·ragflow
geekmice1 小时前
Thymeleaf传递复杂对象参数解决思路
开发语言·lua
我超级能吃的1 小时前
线程池核心原理及使用
java·开发语言