需求

指标基本格式:

clm.{type}.{hostId}.$metricItem

示例1:

// 待匹配表达式:<hostId: 为36位的UUID>
summarize(clm.pm.xxx.yyy.uuu.zzz.0193f1b3-7bcc-4374-8546-8e87b7276003.agg.cpu.percent-avg.system,'10min','avg',true) 希望匹配出:
- type: pm.xxx.yyy.uuu.zzz
- hostId: 0193f1b3-7bcc-4374-8546-8e87b7276003 返回的Map为:
{hostId=0193f1b3-7bcc-4374-8546-8e87b7276003, type=pm.xxx.yyy.uuu.zzz}

示例2:

// 待匹配表达式:<hostId: 为36位的UUID>
summarize(clm.pm.0193f1b3-7bcc-4374-8546-8e87b7276003.agg.cpu.percent-avg.system,'10min','avg',true) 希望匹配出:
- type: pm
- hostId: 0193f1b3-7bcc-4374-8546-8e87b7276003 返回的Map为:
{hostId=0193f1b3-7bcc-4374-8546-8e87b7276003, type=pm}

示例3:

// 待匹配表达式:<hostId: 使用 "_"分割的IP地址>
summarize(clm.pm.xxx.yyy.uuu.zzz.10_144_202_141.agg.cpu.percent-avg.system,'10min','avg',true) 希望匹配出:
- type: pm.xxx.yyy.uuu.zzz
- hostId: 0193f1b3-7bcc-4374-8546-8e87b7276003 返回的Map为:
{hostId=10_144_202_141, type=pm.xxx.yyy.uuu.zzz}

基本思路

使用正则表达式的group()去获取结果;

  • group()正则表示中,使用小括号()表示不同的group,有多少个开括号(,就会有多少个组,表示为:group(0)、group(1)、group(N);
  • group()正则表示中,可以为不同的group添加名称,如<type>或<hostId>,方便匹配;

对于示例1和示例2,可使用下面的group()表达式去匹配:

// hostId: 为36位的UUID
"^.*clm\\.(?<type>\\w+\\.*.*)\\.(?<hostId>\\w{8}(?:-\\w{4}){3}-\\w{12}?)" 解析:
上面包括多个组,下面仅介绍感兴趣的组,比如:
1. (?<type>\\w+\\.*.*) : 别名为 type,匹配此()内的值;
2. (?<hostId>\\w{8}(?:-\\w{4}){3}-\\w{12}?): 别名为 hostId,匹配此()内的值(注:为最外层的小括号)

对于示例3,可使用下面的group()表达式去匹配:

// hostId: 使用 "_"分割的IP地址
"^.*clm\\.(?<type>\\w+\\.*.*)\\.(?<hostId>\\d{0,3}_\\d{0,3}_\\d{0,3}_\\d{0,3})"

代码实现

RegexGroupUtils.java

import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class RegexGroupUtils {
private static final Pattern groupAlias = Pattern.compile("\\<(.*?)\\>"); /**
* 使用正则表达式的group,查找出String中的参数值;<br/>
* 示例如下:
* <pre>{@code
* // 格式:
* clm.{type}.{hostId}.$metricItem
*
* // 待匹配表达式:<hostId: 为36位的UUID>
* summarize(clm.pm.xxx.yyy.uuu.zzz.0193f1b3-7bcc-4374-8546-8e87b7276003.agg.cpu.percent-avg.system,'10min','avg',true)
*
* 希望匹配出:
* - type: pm.xxx.yyy.uuu.zzz
* - hostId: 0193f1b3-7bcc-4374-8546-8e87b7276003
*
* 返回的Map为:
* {hostId=0193f1b3-7bcc-4374-8546-8e87b7276003, type=pm.xxx.yyy.uuu.zzz}
* }</pre>
*
* @param sourceString 待匹配的字符串
* @param pattern 正则表达式
* @return
*/
public static Map<String, String> findParams(String pattern, String sourceString) {
Map<String, String> mapResult = Maps.newConcurrentMap(); if (Strings.isNullOrEmpty(sourceString) || ObjectUtils.isEmpty(pattern)) {
return mapResult;
} // 找出pattern中以"<xxxx>"表示的组别名
Set<String> groupNames = PlaceHolderReplaceUtils.findPlaceHolderKeys(pattern, groupAlias);
if (CollectionUtils.isEmpty(groupNames)) {
return mapResult;
} // 创建 Pattern 对象
Pattern r = Pattern.compile(pattern); // 现在创建 matcher 对象
Matcher m = r.matcher(sourceString);
if (m.find()) {
for (String param : groupNames) {
String value = m.group(param);
if (!Strings.isNullOrEmpty(value)) {
mapResult.put(param, value);
}
}
} return mapResult;
} }

PlaceHolderReplaceUtils.java

import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* Desc: 占位符替换, 占位符表示为:{@code {placeholder}};
* <p>
* 示例:替换如下{xxx}占位符中的内容
* <pre>"名字:{name},年龄:{age},学校:{school}"</pre>
*/
public class PlaceHolderReplaceUtils {
private static final Pattern pattern = Pattern.compile("\\{(.*?)\\}");
private static Matcher matcher; /**
* 查找String中的占位符keys;<br/>
* 示例: "名字:{name},年龄:{age},学校:{school}", 则返回:Set[name,age,school]
* <p>
* pattern示例:
* <pre> {@code
* // 尖括号:<placeHolder> 表示为占位符
* Pattern pattern = Pattern.compile("\\<(.*?)\\>");
*
* // 大括号:{placeHolder} 表示为占位符, 上面的示例中就使用{}作为占位符
* Pattern pattern = Pattern.compile("\\{(.*?)\\}");
* }
* </pre>
*
* @param sourceString
* @param pattern
* @return
*/
public static Set<String> findPlaceHolderKeys(String sourceString, Pattern pattern) {
Set<String> placeHolderSet = Sets.newConcurrentHashSet(); if (Strings.isNullOrEmpty(sourceString) || ObjectUtils.isEmpty(pattern)) {
return placeHolderSet;
} String targetString = sourceString;
matcher = pattern.matcher(sourceString);
while (matcher.find()) {
String key = matcher.group(); //示例: {name}
String placeHolder = key.substring(1, key.length() - 1).trim(); //示例: name
placeHolderSet.add(placeHolder);
} return placeHolderSet;
} }

测试代码

import org.junit.Test;

public class RegexGroupUtilsTest {
@Test
public void findParams() {
//-----------start 测试匹配 uuid(32-36位)
String line1 = "summarize(clm.pm.xxx.yyy.uuu.zzz.0193f1b3-7bcc-4374-8546-8e87b7276003.agg.cpu.percent-avg.system,'10min','avg'," +
"true)";
String line2 = "summarize(clm.pm.0193f1b3-7bcc-4374-8546-8e87b7276003.agg.cpu.percent-avg.system,'10min','avg',true)";
String pattern = "^.*clm\\.(?<type>\\w+\\.*.*)\\.(?<hostId>\\w{8}(?:-\\w{4}){3}-\\w{12}?)"; //OK System.out.println("-----line1--------");
System.out.println(RegexGroupUtils.findParams(pattern, line1).toString());
System.out.println("-----line2--------");
System.out.println(RegexGroupUtils.findParams(pattern, line2).toString());
//-----------end 测试匹配 uuid(32-36位) //-----------start 测试匹配 ip(下划线分割)
System.out.println("----------------IP------------");
String lineIp = "summarize(clm.pm.xxx.yyy.uuu.zzz.10_144_202_141.agg.cpu.percent-avg.system,'10min','avg'," +
"true)";
String patternIp = "^.*clm\\.(?<type>\\w+\\.*.*)\\.(?<hostId>\\d{0,3}_\\d{0,3}_\\d{0,3}_\\d{0,3})";
System.out.println(RegexGroupUtils.findParams(patternIp, lineIp).toString());
//-----------start 测试匹配 ip(下划线分割)
}
/**
* 输出:
*
* -----line1--------
* {hostId=0193f1b3-7bcc-4374-8546-8e87b7276003, type=pm.xxx.yyy.uuu.zzz}
* -----line2--------
* {hostId=0193f1b3-7bcc-4374-8546-8e87b7276003, type=pm}
* ----------------IP------------
* {hostId=10_144_202_141, type=pm.xxx.yyy.uuu.zzz}
*/
}

相关链接

【占位符替换】替换String中的占位符标志位{placeholder}

【正则表达式】使用正则表达式的group,查找出String中的参数值的更多相关文章

  1. Java-J2SE学习笔记-查找一个String中,subString的出现次数

    1.查找一个String中,subString的出现次数 2.代码 package Test; public class TestStringContain { public static void ...

  2. 查找一个String中存储的多个数据

    String类型字符串currVal中, 以“,”分隔单个数据,以“|”分隔每组数据: 代码: var tempuseridstart = String.indexOf( ",", ...

  3. 【转载】C#中List集合使用LastOrDefault方法查找出最后一个符合条件的元素

    在C#的List集合中,FirstOrDefault方法一般用来查找List集合中第一个符合条件的对象,如果未查到则返回相应默认值.其实如果要查找最后一个符合条件的List集合元素对象,可以使用Las ...

  4. Js 利用正则表达式和replace函数获取string中所有被匹配到的文本

    js的replace函数除了替换文本以外还有获取所有被正则表达式匹配到的文本的功能.这里以一个简单的案例来作为演示. 利用正则查找出所有被两个花括号包裹的字符串: var str = '<div ...

  5. JAVA正则表达式匹配,替换,查找,切割(转)

    import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  6. 在UltraEdit的查找和替换中使用正则表达式 (转)

    很多朋友都用过或者正在用UltraEdit,这个编辑器陪伴我也好几年了,从很多地方影响着我写代码的快捷键习惯,Ultraedit提供了非常丰富的编辑功能,其中非常重要的查找和替换功能一定大家都用过,U ...

  7. 正则表达式--C#正则表达式的符号及例子

    正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. C#中经常会遇到要查找某一个字 ...

  8. 09.正则表达式re-1.正则表达式

    1.正则表达式概述 正则表达式(英语:Regular Expression,在代码中常简写为regex.regexp或RE),是计算机科学的一个概念. 正则表达式使用单个字符串来描述.匹配一系列匹配某 ...

  9. linux正则表达式(基础正则表达式+扩展正则表达式)

    正则表达式应用非常广泛,例如:php,Python,java等,但在linux中最常用的正则表达式的命令就是grep(egrep),sed,awk等,换句话 说linux三剑客要想能工作的更高效,就一 ...

随机推荐

  1. Android强制横屏+全屏的几种常用方法

    全屏: 在Activity的onCreate方法中的setContentView(myview)调用之前添加下面代码 1 requestWindowFeature(Window.FEATURE_NO_ ...

  2. 牛客国庆集训派对Day4 J-寻找复读机

    链接:https://www.nowcoder.com/acm/contest/204/J 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他语言20 ...

  3. libsvm使用总结

    ./tools/ subset.py  分割数据集 grid.py   优化参数c.g checkdata.py   检测数据集格式 easy.py   综合 ./windows/ svm-scale ...

  4. (0)MySQL 的指令(包含了解知识点)

    第七章索引:入门安装 - 增删改查基本操作 - 外键(不同表之间的关联) - 数据库的建立和操作 - MySQL的查询操作(模糊.通配.限制符等) - MySQL的引擎 - MySQL的事物(数据回滚 ...

  5. 实验吧—隐写术——WP之 我喜欢培根

    打开解题链接: 有一点点基础的同学大概都知道这是摩尔斯电码,那么我们对他进行解密: 解密后得到: MORSEnullISnullCOOLnullBUTnullBACONnullISnullCOOLER ...

  6. File file = new File("路径名") 路径名的2种写法

    项目的结构:相同颜色是同级的 bean的配置文件的读取和一般文件的读取有点差别的 public static void getValue(String key){ //传入"time&quo ...

  7. Full Schema Stitching with Apollo Server

    转自: https://tomasalabes.me/blog/nodejs/graphql/apollo/2018/09/18/schema-stitiching-apollo.html Full ...

  8. LoadRunner手写脚本、检查点、集合点、事务、思考时间

    手写脚本 什么时候要手写? 可以有条件手写脚本的场景有两类: 有接口说明文档 没有借口说明文档,要去录制,录制不了,抓包手写 所需函数 我们这里讲的例子是基于 http 协议的,也是常见的两种请求类型 ...

  9. day 3 大纲笔记

    01 昨日内容回顾 while 条件: 循环体 如何终止循环: 1,改变条件. 2,break. 3,exit() quit() 不推荐. 关键字: break continue while else ...

  10. [转]ArrayList的实现原理

    1. ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部 ...