Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble implementing partial matches with regular expression on Android

I am creating a regular expression to evaluate if an IP address is a valid multicast address. This validation is occurring in real time while you type (if you type an invalid / out of range character it is not accepted) so I cannot simply evaluate the end result against the regex. The problem I am having with it is that it allows for a double period after each group of numbers (224.. , 224.0.., 224.0.0.. all show as valid).

The code below is a static representation of what's happening. Somehow 224.. is showing as a legal value. I've tested this regex online (non-java'ized: ^2(2[4-9]|3\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$ ) and it works perfectly and does not accept the invalid input i'm describing.

Pattern p = Pattern.compile("^2(2[4-9]|3\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
Matcher m = p.matcher("224..");


if (!m.matches() && !m.hitEnd()) {
    System.out.println("Invalid");
} else {
    System.out.println("Valid");
}

It seems that the method m.hitEnd() is evaluating to true whenever I input 224.. which does not make sense to me. If someone could please look this over and make sure I'm not making any obvious mistake and maybe explain why hitEnd() is returning true in this case I'd appreciate it. Thanks everyone.

like image 277
dymmeh Avatar asked Apr 02 '26 23:04

dymmeh


2 Answers

After doing some evaluating myself (after discovering this was on Android), I realized that the same code responds differently on Dalvik than it does on a regular JVM.

The code is:

   Pattern p = Pattern.compile("^2(2[4-9]|3\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
    Matcher m = p.matcher("224..");

    if (!m.matches() && !m.hitEnd()) {
        System.out.println("Invalid");
    } else {
        System.out.println("Valid");
    }

This code (albeit modified a bit), prints Valid on Android and Invalid on the JVM.

like image 138
Justin Breitfeller Avatar answered Apr 04 '26 14:04

Justin Breitfeller


I do not know how have you tested your regex but it does not look correct according to your description.

Your regext requires all 4 sections of digits. There is no chance it will match 224.. Only [0-1] and \d are marked with question mark and therefore are optional.

So, without dealing with details of limitations of wich specific digits are permitted I'd suggest you something like this:

^\\d{1-3}\\.(\\d{0-3}\\.)?(\\d{0-3}\\.)?(\\d{0-3}\\.)?$

And you do not have to use hitEnd(): $ in the end is enough. And do not use matches(). Use find() instead. matches() is like find() but adds ^ and $ automatically.

like image 43
AlexR Avatar answered Apr 04 '26 14:04

AlexR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!