如何使用正则表达式提取以编号开头、后接多个注解的逻辑分组块
技术百科
心靈之曲
发布时间:2026-01-01
浏览: 次 本文讲解如何用 python 正则表达式精准匹配并分组提取形如“1. @xxx”开头、后续紧跟多个 java 注解(如 `@autowired`、`@override`)的连续文本块,解决单行匹配导致分组断裂的问题。
在处理结构化注释文本(如代码片段、文档标记或测试用例描述)时,常需按逻辑单元提取内容——例如将 "1. @aut1.or\n@Autowired" 视为一个完整条目,而非仅匹配编号行。原始正则 (?:[0-9][.][ ]).+ 仅捕获每行开头的编号项,忽略了换行后紧随的注解行,导致语义割裂。
正确思路是:先识别每个新条目的起始标记(如 ^\d+\.\s+@\w+),再贪婪捕获其后所有连续的注解行(@\w+),直到遇到下一个编号或文本结束。
但由于 re.findall 不支持直接跨行“累积匹配”,推荐采用两阶段策略:
- 预处理文本:统一换行符,确保 \n 可靠分隔;
- 使用 re.finditer 或分步解析,结合上下文状态维护分组。
以下为健壮、可读性强的实现方案:
import re
txt = '''1. @aut1.or
@Autowired
2. @Override
@param
@SuppressWarnings'''
# 步骤1:用正则定位所有“编号行”位置(含换行符边界)
pattern = r'(\d+\.\s+@\w+\S*)\s*(?=(?:\n@\w+\S*)*?(?=\n\d+\.|\Z))'
# 解析说明:
# - (\d+\.\s+@\w+\S*) → 捕获编号行首个注解(如 "1. @aut1.or")
# - (?=...) → 正向先行断言,确保后续是零或多个 "\n@...",且以 "\n数字." 或文本结尾终止
# 步骤2:逐个提取完整块(含后续注解)
blocks = []
for match in re.finditer(pattern, txt, re.MULTILINE):
start_pos = match.start()
# 从匹配起点开始,提取到下一个编号前的所有行(含当前行)
block_end = re.search(r'\n(?=\d+\. )', txt[start_pos:], re.DOTALL)
end_pos = block_end.end() + start_pos if block_end else len(txt)
full_block = txt[start_pos:end_pos].strip()
blocks.append(full_block)
print(blocks)
# 输出:['1. @aut1.or\n@Autowired', '2. @Override\n@param\n@SuppressWarnings']⚠️ 注意事项:
- 原答案中 re.findall(r'(\d+. @\w+.\w+)|(@\w+)' 的写法依赖字符串扁平化(无换行),实际输入含多行时会失效,不推荐用于真实换行文本;
- re.MULTILINE 模式下 ^/$ 匹配每行首尾,但 . 默认不匹配 \n,需显式使用 [\s\S] 或 re.DOTALL;
- 若文本格式更复杂(含空行、缩进、注释混杂),建议改用 pyparsing 或按行迭代的手动状态机解析,正则易维护性下降。
总结:正则适用于规则明确的轻量文本分组,关键在于合理设计锚点(如 ^, \n, \d+\.)与断言((?=...)),避免过度依赖 .+ 这类模糊匹配。对结构化数据,优先保证可读
性与可扩展性,必要时让位于清晰的循环逻辑。
# python
# app
# java
# red
# 正则表达式
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- PHP接收参数值为空怎么办_判断和处理空参数方法说
- Go 中实现 Python urllib.quot
- php内存溢出怎么排查_php内存限制调试与优化方
- C++友元类使用场景_C++类间协作设计方式讲解
- 如何使用Golang理解结构体指针方法接收者_Go
- Python技术债务管理_长期维护解析【教程】
- Win11怎么修复系统文件_使用sfc命令修复Wi
- LINUX怎么进行文本内容搜索_Linux gre
- Windows Defender扫描失败怎么办_安
- c++ reinterpret_cast怎么用 c
- php打包exe怎么传递参数_命令行参数接收方法【
- Win11怎么设置虚拟内存最佳大小_Windows
- Win10系统映像怎么恢复 Win10使用系统映像
- 如何高效删除 NumPy 二维数组中所有元素相同的
- PHP主流架构怎么监控运行状态_工具推荐【操作】
- 如何减少Golang内存碎片化_Golang内存分
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Win11怎么查看已连接wifi密码 Win11查
- Win11怎样激活系统密钥_Win11系统密钥激活
- Win11如何设置开机自动联网 Win11宽带连接
- c# 在高并发下使用反射发射(Reflection
- 如何在Golang中实现RPC异步返回_Golan
- XSLT怎么生成动态的HTML属性名和标签名
- 如何在Golang中处理模块冲突_解决依赖版本不兼
- Win11如何更改任务栏颜色 Win11自定义任务
- php增删改查报错1054怎么办_字段名错误排查修
- Win10怎样清理C盘爱奇艺缓存_Win10清理爱
- Python异步编程高级项目教程_asyncio协
- 如何使用Golang实现云原生应用弹性伸缩_自动应
- Windows10电脑怎么设置电源按钮_Win10
- c++如何用AFL++进行模糊测试 c++ Fuz
- Python面向对象实战讲解_类与设计模式深入理解
- 如何在 ACF 中正确更新嵌套多层的 Group
- Windows11怎样开启游戏模式_Windows
- Win11如何卸载OneDrive_Win11卸载
- LINUX如何查看文件类型_Linux中file命
- Win10如何卸载自带Edge_Win10彻底卸载
- Python脚本参数接收_sys与argparse
- C++如何使用std::transform批量处理
- c++怎么处理多线程死锁_c++ lock_gua
- Windows服务无法启动错误1067是什么_进程
- C++如何编写函数模板?(泛型编程入门)
- Win11截图快捷键是什么_Win11自带截图工具
- MAC怎么用连续互通相机里的“桌上视角”_MAC在
- 如何高效识别并拦截拼接式恶意域名 spam
- 如何在Golang中优化文件读写性能_使用缓冲和并
- php在Linux怎么部署_LNMP环境搭建PHP
- mac怎么安装pip_MAC Python pip
- 获取 PHP 文件最后修改时间的正确方法
- 如何使用正则表达式提取以编号开头、后跟多个注解的完

QQ客服