• 【正则表达式】使用正则表达式的group,查找出String中的参数值


    需求

    指标基本格式:

    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}

  • 相关阅读:
    Hibernate 缓存机制
    Java 对象的串行化(Serialization)
    Java HashMap的死循环
    大牛给计算机专业学生的 7 个建议
    手机的未来
    Java虚拟机类加载机制
    JAVA中的数组是对象吗?
    JAVA中toString方法的作用
    探索哪个进程使磁盘I/O升高
    Linux运维之如何查看目录被哪些进程所占用,lsof命令、fuser命令
  • 原文地址:https://www.cnblogs.com/ssslinppp/p/7928082.html
Copyright © 2020-2023  润新知