From 5646a1c3c0589a756372c433cfa5c8293961f90e Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 5 Mar 2021 22:37:41 +0800 Subject: [PATCH] add StrMatcher --- CHANGELOG.md | 1 + .../java/cn/hutool/core/text/StrMatcher.java | 103 ++++++++++++++++++ .../cn/hutool/core/text/StrMatcherTest.java | 16 +++ 3 files changed, 120 insertions(+) create mode 100644 hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/text/StrMatcherTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c9cee9314..67ed84e2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * 【core 】 IterUtil和CollUtil增加isEqualList方法(issue#I3A3PY@Gitee) * 【crypto 】 增加PBKDF2(issue#1416@Github) * 【core 】 增加FuncKeyMap(issue#1402@Github) +* 【core 】 增加StrMatcher(issue#1379@Github) ### Bug修复 * 【socket 】 修复Client创建失败资源未释放问题。 diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java b/hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java new file mode 100644 index 000000000..f6ef39c98 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/text/StrMatcher.java @@ -0,0 +1,103 @@ +package cn.hutool.core.text; + +import cn.hutool.core.lang.Console; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 字符串模式匹配,使用${XXXXX}作为变量,例如: + * + *
+ *     pattern: ${name}-${age}-${gender}-${country}-${province}-${city}-${status}
+ *     text:    "小明-19-男-中国-河南-郑州-已婚"
+ *     result:  {name=小明, age=19, gender=男, country=中国, province=河南, city=郑州, status=已婚}
+ * 
+ * + * @author looly + * @since 5.6.0 + */ +public class StrMatcher { + + List patterns; + + public StrMatcher(String pattern) { + this.patterns = parse(pattern); + Console.log(this.patterns); + } + + public Map match(String text) { + final HashMap result = MapUtil.newHashMap(true); + int from = 0; + String key = null; + int to; + for (String part : patterns) { + if (StrUtil.isWrap(part, "${", "}")) { + // 变量 + key = StrUtil.sub(part, 2, part.length() - 1); + } else { + to = text.indexOf(part, from); + if (null != key && to > from) { + // 变量对应部分有内容 + result.put(key, text.substring(from, to)); + } + from = to + 1; + key = null; + } + } + + if (null != key && from < text.length()) { + // 变量对应部分有内容 + result.put(key, text.substring(from)); + } + + return result; + } + + /** + * 解析表达式 + * @param pattern 表达式,使用${XXXX}作为变量占位符 + * @return 表达式 + */ + private static List parse(String pattern) { + List patterns = new ArrayList<>(); + final int length = pattern.length(); + char c = 0; + char pre; + boolean inVar = false; + StrBuilder part = StrUtil.strBuilder(); + for (int i = 0; i < length; i++) { + pre = c; + c = pattern.charAt(i); + if (inVar) { + part.append(c); + if ('}' == c) { + // 变量结束 + inVar = false; + patterns.add(part.toString()); + part.clear(); + } + } else if ('{' == c && '$' == pre) { + // 变量开始 + inVar = true; + final String preText = part.subString(0, part.length() - 1); + if (StrUtil.isNotEmpty(preText)) { + patterns.add(preText); + } + part.reset().append(pre).append(c); + } else { + // 普通字符 + part.append(c); + } + } + + if (part.length() > 0) { + patterns.add(part.toString()); + } + return patterns; + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/text/StrMatcherTest.java b/hutool-core/src/test/java/cn/hutool/core/text/StrMatcherTest.java new file mode 100644 index 000000000..12c59c840 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/text/StrMatcherTest.java @@ -0,0 +1,16 @@ +package cn.hutool.core.text; + +import cn.hutool.core.lang.Console; +import org.junit.Test; + +import java.util.Map; + +public class StrMatcherTest { + + @Test + public void matcherTest(){ + final StrMatcher strMatcher = new StrMatcher("${name}-${age}-${gender}-${country}-${province}-${city}-${status}"); + final Map match = strMatcher.match("小明-19-男-中国-河南-郑州-已婚"); + Console.log(match); + } +}