Browse Source

add StrMatcher

Looly 4 years ago
parent
commit
5646a1c3c0

+ 1 - 0
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创建失败资源未释放问题。

+ 103 - 0
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}作为变量,例如:
+ *
+ * <pre>
+ *     pattern: ${name}-${age}-${gender}-${country}-${province}-${city}-${status}
+ *     text:    "小明-19-男-中国-河南-郑州-已婚"
+ *     result:  {name=小明, age=19, gender=男, country=中国, province=河南, city=郑州, status=已婚}
+ * </pre>
+ *
+ * @author looly
+ * @since 5.6.0
+ */
+public class StrMatcher {
+
+	List<String> patterns;
+
+	public StrMatcher(String pattern) {
+		this.patterns = parse(pattern);
+		Console.log(this.patterns);
+	}
+
+	public Map<String, String> match(String text) {
+		final HashMap<String, String> 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<String> parse(String pattern) {
+		List<String> 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;
+	}
+}

+ 16 - 0
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<String, String> match = strMatcher.match("小明-19-男-中国-河南-郑州-已婚");
+		Console.log(match);
+	}
+}