Java用正则表达式获取特征字符串
Posted 汪小哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java用正则表达式获取特征字符串相关的知识,希望对你有一定的参考价值。
1、正则表达式
正则表达式是一个非常高深的艺术、在编程过程中无论你写没有写过,时刻也使用过相关的工具 比如shell 中的一些常见的grep 、less 等等工具。
推荐一个非常好用的教程工具。
https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md
2、背景
很久之前,需要实现一个功能 从一个字符串中获取到 特征字符串,这里使用案号作为例子
(2020)浙0106民督28号-1
将上诉的案号信息 提取为如下的信息
caseCodeYear=2020
caseCodeCourtPronoun=浙0106
caseCodeTypePronoun=民督
caseCodeNumber=28
3、实现方案
3.1 java.lang.String#replaceAll
使用java.lang.String#replaceAll 中 获取regex 分组 $1 $2 $3 来进行获取 ,stackoverflow 中有个非常好玩的例子 https://stackoverflow.com/questions/36267354/java-string-replaceall-with-back-reference/36267574
@Test
public void getRegexReplace()
String regex = ".(\\\\d4).([\\\\u4e00-\\\\u9fa5]\\\\d0,4)([\\\\u4e00-\\\\u9fa5]0,5)(\\\\d+)号.*";
String descStr = "(2020)浙0106民督28号-1";
String caseCodeYear = descStr.replaceAll(regex, "$1");
String caseCodeCourtPronoun = descStr.replaceAll(regex, "$2");
String caseCodeTypePronoun = descStr.replaceAll(regex, "$3");
String caseCodeNumber = descStr.replaceAll(regex, "$4");
log.info("caseCodeYear= caseCodeCourtPronoun=,caseCodeTypePronoun=,caseCodeNumber=", caseCodeYear,
caseCodeCourtPronoun, caseCodeTypePronoun, caseCodeNumber);
//当然也可以一口气搞定
String allSpit = descStr.replaceAll(regex, "$1|$2|$3|$4");
log.info("all split=",allSpit);
15:44:44.890 [main] INFO com.RegexExample - caseCodeYear=2020 caseCodeCourtPronoun=浙0106,caseCodeTypePronoun=民督,caseCodeNumber=28
15:44:44.924 [main] INFO com.RegexExample - all=2020|浙0106|民督|28
3.2 java.util.regex.Matcher#matches + java.util.regex.Matcher#groupCount
matches()是全部匹配,是将整个输入串与模式匹配 ,如果修改为 (2020)6浙0106民督28号-1 就不匹配了
@Test
public void getRegexByGroup()
String regex = ".(\\\\d4).([\\\\u4e00-\\\\u9fa5]\\\\d0,4)([\\\\u4e00-\\\\u9fa5]0,5)(\\\\d+)号.*";
String caseCode = "(2020)浙0106民督28号-1";
Pattern compile = Pattern.compile(regex);
Matcher matcher = compile.matcher(caseCode);
if (matcher.matches())
for (int i1 = 0; i1 <= matcher.groupCount(); i1++)
log.info("group=,groupValue=", i1, matcher.group(i1));
15:36:13.466 [main] INFO com.RegexExample - group=0,groupValue=(2020)浙0106民督28号-1
15:36:13.500 [main] INFO com.RegexExample - group=1,groupValue=2020
15:36:13.500 [main] INFO com.RegexExample - group=2,groupValue=浙0106
15:36:13.500 [main] INFO com.RegexExample - group=3,groupValue=民督
15:36:13.500 [main] INFO com.RegexExample - group=4,groupValue=28
3.3 java.util.regex.Matcher#find()+java.util.regex.Matcher#groupCount
find()方法是部分匹配,是查找输入串中与模式匹配的子串,如果该匹配的串有组还可以使用group()函数。
匹配的子串 的意思 可以存在多个相匹配的字符串。
3.3.1 正则匹配单个子串的例子
@Test
public void getRegexCodeFind1()
String regex = ".(\\\\d4).([\\\\u4e00-\\\\u9fa5]\\\\d0,4)([\\\\u4e00-\\\\u9fa5]0,5)(\\\\d+)号.*";
String descStr = "(2020)浙0106民督28号-1";
log.info(descStr.length() + "");
Pattern compile = Pattern.compile(regex);
Matcher matcher = compile.matcher(descStr);
while (matcher.find())
// INFO com.RegexExample - start=0 end=18
log.info("start= end=", matcher.start(), matcher.end());
for (int i1 = 0; i1 <= matcher.groupCount(); i1++)
log.info("group=,groupValue=", i1, matcher.group(i1));
15:38:55.381 [main] INFO com.RegexExample - 18
15:38:55.388 [main] INFO com.RegexExample - start=0 end=18
15:38:55.391 [main] INFO com.RegexExample - group=0,groupValue=(2020)浙0106民督28号-1
15:38:55.391 [main] INFO com.RegexExample - group=1,groupValue=2020
15:38:55.391 [main] INFO com.RegexExample - group=2,groupValue=浙0106
15:38:55.391 [main] INFO com.RegexExample - group=3,groupValue=民督
15:38:55.391 [main] INFO com.RegexExample - group=4,groupValue=28
3.3.2 正则匹配多个的例子
@Test
public void getRegexCodeFind2()
String regex = "\\\\d=([^(,+)]*)";
String desStr = "0=房源序号, 1=序号, 2=合同编号, 3=项目名称";
log.info(desStr.length() + "");
Pattern compile = Pattern.compile(regex);
Matcher matcher = compile.matcher(desStr);
while (matcher.find())
// INFO com.RegexExample - start=0 end=18
log.info("start= end=", matcher.start(), matcher.end());
for (int i1 = 0; i1 <= matcher.groupCount(); i1++)
log.info("group=,groupValue=", i1, matcher.group(i1));
15:50:06.028 [main] INFO com.RegexExample - 30
15:50:06.033 [main] INFO com.RegexExample - start=1 end=7
15:50:06.035 [main] INFO com.RegexExample - group=0,groupValue=0=房源序号
15:50:06.035 [main] INFO com.RegexExample - group=1,groupValue=房源序号
15:50:06.035 [main] INFO com.RegexExample - start=9 end=13
15:50:06.035 [main] INFO com.RegexExample - group=0,groupValue=1=序号
15:50:06.036 [main] INFO com.RegexExample - group=1,groupValue=序号
15:50:06.036 [main] INFO com.RegexExample - start=15 end=21
15:50:06.036 [main] INFO com.RegexExample - group=0,groupValue=2=合同编号
15:50:06.036 [main] INFO com.RegexExample - group=1,groupValue=合同编号
15:50:06.036 [main] INFO com.RegexExample - start=23 end=29
15:50:06.036 [main] INFO com.RegexExample - group=0,groupValue=3=项目名称
15:50:06.036 [main] INFO com.RegexExample - group=1,groupValue=项目名称
4、stackoverflow 一个有趣的replaceall的问题
https://stackoverflow.com/questions/36267354/java-string-replaceall-with-back-reference/36267574
There is a Java Regex question: Given a string, if the " * " is at the start or the end of the string, keep it, otherwise, remove it. For example: 只保留前后的* 其他的去掉
@Test
public void stackoverflow()
String desStr = "**abc**def*";
String $1$2 = desStr.replaceAll("(^\\\\*)|(\\\\*$)|\\\\*", "$1$2");
log.info("$1$2 =", $1$2);
如何去验证这个打开 正则表达式的学习网址
https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md 然后学习跳转到具体的学习网址 输入这个表达式 (^\\)|(\\$)|\\* 可以简单的理解,匹配第一个是* 或者 最后一个是* 或者 中间是* 的字符串,然后通过group1 group2 的值去替换匹配到的group的值的信息。
4.1 验证一下每次group 匹配到的是什么?
@Test
public void stackoverflow1()
String regex = "(^\\\\*)|(\\\\*$)|\\\\*";
String desStr = "**abc**def*";
Pattern compile = Pattern.compile(regex);
Matcher matcher = compile.matcher(desStr);
while (matcher.find())
// INFO com.RegexExample - start=0 end=18
log.info("start= end=", matcher.start(), matcher.end());
for (int i1 = 0; i1 <= matcher.groupCount(); i1++)
log.info("group=,groupValue=", i1, matcher.group(i1));
从下面的数据分析一下:group=0 可以忽略这个就是当前group组的全部数据;
在前面的* ,匹配到的时候 总会有 group2 数据为空 =>replace 为一个*
最后面的* ,匹配到的时候 总会有 group1 数据为空 => replace 为一个*
中间匹配到的* 匹配到的时候 总会有 group1 group2 数据为空 =>replace 为空
如此 刚刚好解释了上面的一个问题。
16:11:45.754 [main] INFO com.RegexExample - start=0 end=1
16:11:45.767 [main] INFO com.RegexExample - group=0,groupValue=*
16:11:45.767 [main] INFO com.RegexExample - group=1,groupValue=*
16:11:45.767 [main] INFO com.RegexExample - group=2,groupValue=null
16:11:45.767 [main] INFO com.RegexExample - start=1 end=2
16:11:45.767 [main] INFO com.RegexExample - group=0,groupValue=*
16:11:45.767 [main] INFO com.RegexExample - group=1,groupValue=null
16:11:45.767 [main] INFO com.RegexExample - group=2,groupValue=null
16:11:45.767 [main] INFO com.RegexExample - start=5 end=6
16:11:45.768 [main] INFO com.RegexExample - group=0,groupValue=*
16:11:45.768 [main] INFO com.RegexExample - group=1,groupValue=null
16:11:45.768 [main] INFO com.RegexExample - group=2,groupValue=null
16:11:45.768 [main] INFO com.RegexExample - start=6 end=7
16:11:45.768 [main] INFO com.RegexExample - group=0,groupValue=*
16:11:45.768 [main] INFO com.RegexExample - group=1,groupValue=null
16:11:45.768 [main] INFO com.RegexExample - group=2,groupValue=null
16:11:45.768 [main] INFO com.RegexExample - start=10 end=11
16:11:45.768 [main] INFO com.RegexExample - group=0,groupValue=*
16:11:45.768 [main] INFO com.RegexExample - group=1,groupValue=null
16:11:45.768 [main] INFO com.RegexExample - group=2,groupValue=*
以上是关于Java用正则表达式获取特征字符串的主要内容,如果未能解决你的问题,请参考以下文章