使用正则分组匹配字符串

Posted in java on 2022-5-1 by 王登武 ‐ 1 min read

使用正则分组匹配字符串

字符串匹配

假设有这样一个Redis连接字符串:“redis://hello1234@master.dengwu.wang:6379”,我们需要提取其中的redis部分和hello1234,以及host和port,如何获取呢?首先想到的是,可以通过split分隔,然后提取其中每个部分,这样做也可以,但是整个操作是基于命令式的,不够语义化,导致理解起来需要了解每个步骤,而且如果增加内容,可能需要对整个操作进行修改,比如可能需要解析多个服务器地址:“redis://hello1234@master.dengwu.wang:6379,slave1.dengwu.wang:6380”。

使用正则分组

正则表达式里,有分组的概念,即通过()的方式,可以分组匹配,这样通过分组,就可以将一个长字符串,分割成语义明确的子字符串,方便匹配。 比如上面的字符串:“redis://hello1234@master.dengwu.wang:6379,slave1.dengwu.wang:6380”,可以分成5个部分:

  1. redis是协议分组,可能有redis,rediss,redis-cluster,rediss-cluster
  2. hello1234是密码分组,可能会有各种特殊字符,比如:@:,等等内容,你没办法限定密码设定里的字符内容
  3. master.dengwu.wang:6379,slave1.dengwu.wang:6380这部分统称为right部分分组,需要借助,分隔成host:port内容
  4. master.dengwu.wang部分是host分组
  5. 6379是port分组

看下代码实现:

//定义protocol分组,使用?<name>来命名分组
private static final String protocolGroup = "(?<protocol>redis|rediss|redis-cluster|rediss-cluster)";
private static final String passwordGroup = "(?<password>.*)";
private static final String rightGroup = "(?<right>[\\w.:,?=]+)";
private static final String hostGroup = "(?<host>.+)";
private static final String portGroup = "(?<port>\\d+)";
private static final Pattern patternAll = Pattern.compile(protocolGroup + "://" + passwordGroup + "@" + rightGroup);
private static final Pattern patternServer = Pattern.compile(hostGroup + ":" + portGroup);
Matcher matcherAll = patternAll.matcher("rediss://hello1234@master.dengwu.wang:6379,slave1.dengwu.wang:6380");
    if (matcherAll.matches()) {
        String protocol = matcherAll.group("protocol");
        String password = matcherAll.group("password");
        String rightStr = matcherAll.group("right");
        String[] servers = rightStr.split(",");
        for (String server : servers) {
            Matcher matcherServer = patternServer.matcher(server);
            if (matcherServer.matches()) {
                String host = matcherCluster.group("host");
                String port = matcherCluster.group("port");
            }
        }
    }

通过分组匹配,就可以很方便的使用.group(分组名称),语义化的得到字符串内容,避免了大量split操作导致的理解困难,另外因为password分组使用了贪婪模式,所以可以兼容任意特殊字符串,避免了split时,特殊字符串导致的split未按预期拆分。

Top