Java正则表达式的一点使用

近来写自动化程序用到了Java正则表达式,一个小坑记录一下

Java正则表达式的用法有很多文章会写,基本上是这样子的:

String normalReg = "\\d{5}";
Pattern p = Pattern.compile(normalReg);
Matcher m = p.matcher(srcStr);

然后就可以用Matcher的对象m做很多事情啦。写一个函数先:

public static void testReg(String srcStr) {
        
        String normalReg = "\\d{5}";
        Pattern p = Pattern.compile(normalReg);
        Matcher m = p.matcher(srcStr);
        if (m.find()) {
            System.out.println(m.group(0));
        }
        
    }

然后调用它,

String test = "aaa1234567bbb";

testReg(test);

输出为:12345

对象m还可以调用matches(),将函数testReg中的m.find() 改成m.matches()看看啥效果,运行,等待,等待,会发现是空的。

查看下文档,发现matches()只有字符串全部匹配才返回true,否则返回false,而可爱的find()不同,它是只要有匹配的就要返回,所以要想matches()返回true,可以改下正则表达式为:

String normalReg = "\\w*\\d*\\w*";

再运行一下,可以看到结果为:aaa1234567bbb,也就是要匹配的原始字符串。

但是我的需求其实没有这么简单。我要匹配的字符串其实是这个样子的:

String time = "\"effectiveStartTime\": \"$current_time+1h\",\"effectiveEndTime\": \"$current_time\";

匹配所有以$current_time开头的字符串,如果后面没有+或者-,就返回当前时间,否则就按照算式返回计算后的时间。

如果只是匹配一个,那么可以很简单的用find()和replace搞定,也就是大概这样:

public static String testReg(String srcStr) {
        char op;
        char unit;
        int offset;
        String result;
        String timespan = null;
        Instant inst = Instant.now();
        Instant inst1 = null;
        StringBuffer sb = new StringBuffer();
        String normalReg = "(\\$current_time)\\s*([+|-]?)\\s*(\\d*)\\s*([d|h|m]?)";
        Pattern p = Pattern.compile(normalReg);
        Matcher m = p.matcher(srcStr);

        if (m.find()) {
            try {
                if (m.group(2).equals("")) {
                    return m.replaceFirst(String.valueOf(System.currentTimeMillis()));
                    
                }
                op = m.group(2).charAt(0);
                offset = Integer.parseInt(m.group(3));
                unit = m.group(4).charAt(0);
                if (op == '+') {
                    switch (unit) {
                    case 'm':
                        inst1 = inst.plus(Duration.ofMinutes(offset));
                        break;
                    case 'h':
                        inst1 = inst.plus(Duration.ofHours(offset));
                        break;
                    case 'd':
                        inst1 = inst.plus(Duration.ofDays(offset));
                        break;
                    default:
                        inst1 = inst;
                    }
                } else if (op == '-') {
                    switch (unit) {
                    case 'm':
                        inst1 = inst.minus(Duration.ofMinutes(offset));
                        break;
                    case 'h':
                        inst1 = inst.minus(Duration.ofHours(offset));
                        break;
                    case 'd':
                        inst1 = inst.minus(Duration.ofDays(offset));
                        break;
                    default:
                        inst1 = inst;
                    }
                }
                if (inst1 == null)
                    return srcStr;
                timespan = String.valueOf(inst1.getEpochSecond()).concat("000");
                return m.replaceFirst(timespan);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        }
        return srcStr;
    }

运行一下看看吧:

String time = "\"effectiveStartTime\": \"$current_time+1h\",\"effectiveEndTime\": \"$current_time\",aaaaaaaaaa:\"$current_time\"";

System.out.println(testReg(time));

运行结果为:"effectiveStartTime": "1547208757000","effectiveEndTime": "$current_time",aaaaaaaaaa:"$current_time"

后边的都没有替换,当然可以将replaceFirst改成replaceAll,然后惊喜的发现都替换了,可是呢,替换的时间并不对,这个时候就该appendReplacement()上场了。

appendReplacement()的作用我觉得可以这样理解,利用正则表达式去匹配源字符串,发现一个匹配的字符串,就运行一次计算,然后将结果加到stringbuffer字符串中,然后继续向下匹配一直到最后,但是它并不会把最后匹配的字符串之后的字符加到stringbuffer中,于是还需要另外一个appendTail()来帮忙,所以改造一下函数吧:

public static String testReg(String srcStr) {
        char op;
        char unit;
        int offset;
        String timespan = null;
        Instant inst = Instant.now();
        Instant inst1 = null;
        StringBuffer sb = new StringBuffer();
        String normalReg = "(\\$current_time)\\s*([+|-]?)\\s*(\\d*)\\s*([d|h|m]?)";
        Pattern p = Pattern.compile(normalReg);
        Matcher m = p.matcher(srcStr);

        while (m.find()) {
            try {
                if (m.group(2).equals("")) {
                    m.appendReplacement(sb,String.valueOf(System.currentTimeMillis()));
                    continue;
                }
                op = m.group(2).charAt(0);
                offset = Integer.parseInt(m.group(3));
                unit = m.group(4).charAt(0);
                if (op == '+') {
                    switch (unit) {
                    case 'm':
                        inst1 = inst.plus(Duration.ofMinutes(offset));
                        break;
                    case 'h':
                        inst1 = inst.plus(Duration.ofHours(offset));
                        break;
                    case 'd':
                        inst1 = inst.plus(Duration.ofDays(offset));
                        break;
                    default:
                        inst1 = inst;
                    }
                } else if (op == '-') {
                    switch (unit) {
                    case 'm':
                        inst1 = inst.minus(Duration.ofMinutes(offset));
                        break;
                    case 'h':
                        inst1 = inst.minus(Duration.ofHours(offset));
                        break;
                    case 'd':
                        inst1 = inst.minus(Duration.ofDays(offset));
                        break;
                    default:
                        inst1 = inst;
                    }
                }
                if (inst1 == null)
                    return srcStr;
                timespan = String.valueOf(inst1.getEpochSecond()).concat("000");
                m.appendReplacement(sb, timespan);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        }
        m.appendTail(sb);
        return sb.toString();
    }

再调用下试试:

String time = "\"effectiveStartTime\": \"$current_time+1h\",\"effectiveEndTime\": \"$current_time\",aaaaaaaaaa:\"$current_time\"";

System.out.println(testReg(time));

运行结果为: "effectiveStartTime": "1547209178000","effectiveEndTime": "1547205578660",aaaaaaaaaa:"1547205578660"

每个都替换了,而且还没有错,就是这样了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值