正则表达式高级用法【原】
开发过程中的真实场景
A报文
<?xml version="1.0" encoding="utf-8"?> <PACKET><HEAD><SERVICE_NAME>seeYou</SERVICE_NAME></HEAD><BODY><CONTENT><![CDATA[<?xml version="1.0" encoding="utf-8"?><PACKET><![CDATA[nice to meet you!]]></PACKET>]]></CONTENT></BODY> </PACKET>
嵌套在A报文中的B报文
<?xml version="1.0" encoding="utf-8"?> <PACKET> <![CDATA[nice to meet you! ]]> </PACKET>
场景
我得到A报文,后需要解析提取B报文转发给目标系统.
而现有解析代码PatternTool.java如下:
package kingtool;import java.util.regex.Matcher; import java.util.regex.Pattern;public class PatternTool {/*** 从regex表达式中提供对应的值* @author King*/public static String parsePattern(String regex, String content ,int groupNum) {String ret = "";String str = "";String output ="";try {Pattern p = Pattern.compile(regex);Matcher m = p.matcher(content);if (m.find()) {for(int i = 0 ; i <= m.groupCount() ; i ++){if(i == 0){}else{str = m.group(i);output = String.format("解析得正则表达式%s中group(%d)匹配的值\n",regex,i);System.out.println(output);System.out.println(str);}}ret = m.group(groupNum);System.out.println("返回第"+groupNum+"组匹配到的内容:\n"+ret);}else{System.out.println("未解析到正则表达式"+regex+"匹配的的值\n");}} catch (Exception e) {e.printStackTrace();}return ret;}public static void main(String[] args) {String content = FileTool.readStringFromFile("D://c.txt", "GBK" );//希望匹配<CONTENT>.*<![CDATA[.*]]>.*</CONTENT>String regex = "<CONTENT>(.*)<!\\[CDATA\\[(.*)\\]\\]>(.*)</CONTENT>";String ret = parsePattern(regex,content,2);} }
解析后,打印结果如下(并非最终想要的B报文):
文件 D://c.txt存在与否?: true 读到的文件内容如下: <?xml version="1.0" encoding="utf-8"?><PACKET> <HEAD> <SERVICE_NAME>seeYou</SERVICE_NAME> </HEAD> <BODY> <CONTENT> <![CDATA[ <?xml version="1.0" encoding="utf-8"?> <PACKET> <![CDATA[ nice to meet you! ]]> </PACKET> ]]> </CONTENT> </BODY></PACKET> 解析得正则表达式<CONTENT>(.*)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(1)匹配的值<![CDATA[ <?xml version="1.0" encoding="utf-8"?> <PACKET> 解析得正则表达式<CONTENT>(.*)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(2)匹配的值nice to meet you! ]]> </PACKET> 解析得正则表达式<CONTENT>(.*)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(3)匹配的值返回第3组匹配到的内容:
现在来分析以上原因:
1.因为正则默认是贪婪的(全取模式,能吃多少是多少),所以第一个(.*)先取
然后一点一点从尾部吐出来,直到匹配(<!\[CDATA\[(.*)\]\]>)就停止吐字符,至此 group(1) 匹配结束.
2. 现在来匹配第二个(.*),老规矩先全取
然后一个一个吐字符,直到遇到]]>
3. 最后来匹配第三个(.*),老规矩先全取
直到遇到</CONTENT>停下
最终,这完全不是我们希望看到的匹配结果 nice to meet you! ]]> </PACKET>
解决方案: 加个?变成懒猫模式即可
把PatternTool.java中main主函数的正则匹配式regex中的第一个括号中加一个?,变成懒猫模式
public static void main(String[] args) {String content = FileTool.readStringFromFile("D://c.txt", "GBK" );//希望匹配<CONTENT>.*<![CDATA[.*]]>.*</CONTENT>String regex = "<CONTENT>(.*?)<!\\[CDATA\\[(.*)\\]\\]>(.*)</CONTENT>";String ret = parsePattern(regex,content,2);}
解析后,打印结果如下(是最终想要的B报文):
文件 D://c.txt存在与否?: true 读到的文件内容如下: <?xml version="1.0" encoding="utf-8"?><PACKET> <HEAD> <SERVICE_NAME>seeYou</SERVICE_NAME> </HEAD> <BODY> <CONTENT> <![CDATA[ <?xml version="1.0" encoding="utf-8"?> <PACKET> <![CDATA[ nice to meet you! ]]> </PACKET> ]]> </CONTENT> </BODY></PACKET> 解析得正则表达式<CONTENT>(.*?)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(1)匹配的值解析得正则表达式<CONTENT>(.*?)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(2)匹配的值<?xml version="1.0" encoding="utf-8"?> <PACKET> <![CDATA[ nice to meet you! ]]> </PACKET> 解析得正则表达式<CONTENT>(.*?)<!\[CDATA\[(.*)\]\]>(.*)</CONTENT>中group(3)匹配的值返回第2组匹配到的内容:<?xml version="1.0" encoding="utf-8"?> <PACKET> <![CDATA[ nice to meet you! ]]> </PACKET>
现在来分析以上原因:
1.因为加了?后,正则变成了懒猫模式(特别地懒,能不吃就不吃),所以第一个(.*?)先取
然后一点一点吃字符进来,直到匹配(<!\[CDATA\[(.*)\]\]>)就停止吃字符,至此 group(1) 匹配结束.
2. 现在来匹配第二个(.*),老规矩先全取
然后一个一个吐字符,直到遇到]]>
3. 最后来匹配第三个(.*),老规矩先全取
直到遇到</CONTENT>停下
最终,这就是我们希望看到的匹配结果 :
<?xml version="1.0" encoding="utf-8"?><PACKET><![CDATA[nice to meet you!]]></PACKET> |
总结:
正则默认贪婪模式 : 能取多少是多少
加了?后变成懒猫模式 : 能不取就尽量不取
本文原创,请转明出处,by 金墨痴.
转载于:https://www.cnblogs.com/whatlonelytear/p/5764298.html
正则表达式高级用法【原】相关推荐
- JAVA正则表达式高级用法(分组与捕获)
2019独角兽企业重金招聘Python工程师标准>>> 正则表达式在字符串处理中经常使用,关于正则简单的用法相信有一点程序基础的人都懂得一些,这里就不介绍简单基础了.这里主要讲解一下 ...
- python3.7正则表达式语法_python3正则表达式的几个高级用法
python3正则表达式的几个高级用法 一. 概述 本文举例说明python3正则表达式的一些高级级法,主要是各类分组,可应用于 1.复杂网页文件中的有用数据 例如,采用爬虫技术取得网页后,对网页内任 ...
- js replace不改变原str_总结javascript replace高级用法
详解javascript replace高级用法 在前端与后台交互的时候我们通常都需要将后台传递的数据绑定到html中,这个绑定数据的方式我们通常是使用jQuery或者使用原生的innerHTML进行 ...
- vim的高级用法配置以及在系统中如何获取帮助
vim的高级用法配置以及在系统中如何获取帮助 1 vim的三种模式 1.1 使用方法 1.2 vim模式 2 vim工作的基本配置 2.1 临时设定(set设定) 2.2 永久设定方式 3 搜索 4 ...
- sed的基本用法和高级用法
sed 的详细用法 sed:stream editor 流编辑器 sed的工作模式:sed是一个行文本编辑器,默认每次处理文本中所匹配到一行内容到模式空间,然后用后面的命令进行操作,操作完成之后,会把 ...
- Fiddler 高级用法:Fiddler Script 与 HTTP 断点调试
之前在<关于 WEB/HTTP 调试利器 Fiddler 的一些技巧分享>中系统的介绍过 Fiddler 的原理与一些常见技巧,但那篇文章只是入门科普,并不深入,今天要介绍到的内容相对更加 ...
- python基础和第三方库 笔记(python基础完结包括高级用法,第三方库持续更新中...)
python基础 注:本笔记面向有一定基础的人 本笔记是本人快速复习python过程中记录的,不适合零基础的人学习python的主工具,可以作为辅工具,本笔记记录了入门阶段常用操作,如有错误的地方,希 ...
- Python进阶:切片的误区与高级用法
众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice)就是一种截取索引片段的技术,借助切片 ...
- Git log高级用法
格式化Log输出 首先,这篇文章会展示几种git log格式化输出的例子.大多数例子只是通过标记向git log请求或多或少的信息. 如果你不喜欢默认的git log格式,你可以用git config ...
最新文章
- MongoDB简单操作
- 3年国奖、一作9篇SCI,完美逆袭的中大博士坦言自己也曾濒临挂科
- 关于java中Math的一些用法
- Detach Volume 操作 - 每天5分钟玩转 OpenStack(55)
- MM32F3277 MicroPython 的定时器功能
- 将多个图片转换成PDF文件-img2pdf
- matlab序列谱分析,基于MATLAB序列谱分析及FFT实现快速卷积.pdf
- 基本排序(C语言版)
- 【CuteJavaScript】Angular6入门项目(1.构建项目和创建路由)
- ON DELETE CASCADE和ON UPDATE CASCADE
- CSS的块级元素和内联元素,以及float
- robot framework -重点记录
- 《DNS与BIND(第5版)》——第10章 高级功能10.1 地址匹配列表和ACL
- 太阳当空照-Windows服务化方式instsrv与srvany
- 微信企业消息推送方案
- 初始MySQL数据库
- DROOPYCTF WALKTHROUGH
- 已斥资250亿!东京奥运会的AI黑科技能否如期亮相?
- JQuery获取选中的元素(单选框复选框)及其他等
- 怎么做抖音故障艺术风格人物照片效果