1

Given a strings like:

S5.4.2

3.2

SD45.G.94L5456.294.1004.8888.0.23QWZZZZ

5.44444444444444444444444444444.5GXV

You would need to return:

5.4.2

3.2

5456.294.1004.8888.0.23

5.44444444444444444444444444444.5

Is there a smart way to write a method to extract only the IP address-like number from it? (I say IP Address-like because I'm not sure if IP addresses are usually a set amount of numbers or not). One of my friends suggested that there might be a regex for what I'm looking for and so I found this. The problem with that solution is I think it is limited to only 4 integers total, and also won't expect ints like with 4+ digits in between dots.

I would need it to recognize the pattern:

NUMS DOT (only one) NUMS DOT (only one) NUMS

Meaning:

234..54.89 FAIL

.54.6.10 FAIL

256 FAIL

234.7885.924.120.2.0.4 PASS

Any ideas? Thanks everyone. I've been at this for a few hours and can't figure this out.

Community
  • 1
  • 1
Hatefiend
  • 3,416
  • 6
  • 33
  • 74
  • 1
    IP addresses are only 4 numbers. You will never see a valid IP that is not. Anyways, your friend who recommended regex is correct. That would be the simplest way of matching strings according to your specification. Do you want it to only match IPs (so 4 numbers) or is this for something else? – Piccolo Sep 07 '15 at 20:50
  • @Piccolo IPv6 addresses are **eight** groups of hexadecimal numbers. – ceejayoz Sep 07 '15 at 20:54
  • @Piccolo The number I need to extract from the string must start with an integer, have dots separating integers, must end with an integer, and may be infinitely long (or as long as a String can hold values, so 2.4 million or so). Sorry if this wasn't clear in my post. – Hatefiend Sep 07 '15 at 20:55
  • @ceejayoz Oh right, I always forget about IPv6. – Piccolo Sep 07 '15 at 21:03
  • Here is a regular expression you can use to match them: ``^\d(\.\d+)+$`` and here are my test cases: http://fiddle.re/q76j86 Edit: Just reread the question and this isn't exactly what you're looking for, but hopefully it will set you off on the right track. – Piccolo Sep 07 '15 at 21:14

2 Answers2

2

Here is an approach using Regex:

    private static String getNumbers(String toTest){
        String IPADDRESS_PATTERN =
                "(\\d+\\.)+\\d+";

        Pattern pattern = Pattern.compile(IPADDRESS_PATTERN);
        Matcher matcher = pattern.matcher(toTest);
        if (matcher.find()) {
            return matcher.group();
        }
        else{
            return "did not match anything..";
        }
    }

This will match the number-dot-number-... pattern with an infinite amount of numbers.

I modified this Answer a bit.

Community
  • 1
  • 1
shofstetter
  • 254
  • 1
  • 10
  • That's incredible. How does this work? I'm only in my second year so I haven't gotten to learn Patterns or Matchers of Regex yet. So in the pattern... you did \\d, and \ tells the compiler that a special character is coming. So what does \d mean? It must mean a number, right? Then the \. means period, and finally at the end of the pattern it must have a \d (number). But then how does it know, if given like 5.4.3, not to return 5.4 When it reads 5.4, it now has the #.# pattern it was looking for. What tells it to keep looking for more? Thanks a ton btw. – Hatefiend Sep 07 '15 at 21:32
  • Well the Regex pattern is actually `(\d+\.)+\d+` where `\d` means any digit from 0 to 9. The + means that there needs to be at least one digit. The escaped `\.` means that there literally needs to be a dot after each number. This whole thing `(\d+\.)+` means everything in these braces needs to appear at least once. And finally, `\d+` means there needs to be a number at the end, too. You can copy the regex and test it [here](https://regex101.com/), you'll also see a more detailed explanation. – shofstetter Sep 07 '15 at 21:43
1

There are many ways to do it. This is the best way, I guess.

public static String NonDigits(final CharSequence input)
{
final StringBuilder sb = new StringBuilder(input.length());
for(int i = 0; i < input.length(); i++){
    final char c = input.charAt(i);
    if(c > 47 && c < 58){
        sb.append(c);
    }
}
return sb.toString();
}

A CharSequence is a readable sequence of characters. This interface provides uniform, read-only access to many different kinds of character sequences.

  1. Look at this ASCII Table. The ascii values from 47 to 58 are 0 to 9. So, this is the best possible way to extract the digits than any other way.

  2. "final" keyword is more like if set once, cannot be modified. Declaring string as final is good practise.

Same code, just to understand the code in a better way:

public static String NonDigits(String input)
{
    StringBuilder sb = new StringBuilder(input.length());

    for(int i = 0; i < input.length(); i++)
    {
        char c = input.charAt(i);
        if(c > 47 && c < 58)
        {
            sb.append(c);
        }
}
return sb.toString();
}
Community
  • 1
  • 1
  • 1
    @Shiva_Shinde Wow... something I couldn't write in 250 lines if nested loops and if statements, you wrote in like 20. Could you explain it a bit? Why take in a final CharSequence instead of a String? Are you variables final just to avoid accidentally changing them? What does the line if (c > 47 && c < 58) { sb.append(c); } do? – Hatefiend Sep 07 '15 at 21:07
  • I have updated the answer. Sorry for not making things clear, I didn't know you are in a second year. Great initiative. Keep coding :) –  Sep 07 '15 at 21:55