Validate if input string is a number between 0-255 using regex - java

I am facing problem while matching input string with Regex. I want to validate input number is between 0-255 and length should be up to 3 characters long. code is working fine but when I input 000000 up to any length is shows true instead false.
Here is my code :-
String IP = "000000000000000";
System.out.println(IP.matches("(0*(?:[0-9][0-9]?|[0-2][0-5][0-5]))"));

Tested this:
static String pattern = "^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$";
It works for the following:
IP Addresses xxx.xxx.xxx.xxx / xx.xx.xx.xx / x.x.x.x / mix of these.
Leading zeros are allowed.
Range 0-255 / maximum 3 digts.

You may use this regex:
boolean valid = IP.matches("^(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])$");
// since .matches expects complete match you can omit anchors
boolean valid = IP.matches("(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])");
RegEx Demo

You can use this pattern which matches "0", "1", ... "255":
"([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
Demo on Ideone

Using boundary tags to ensure only (0 to 255) numbers is matched, the optimized pattern that I have to offer is:
\b(?:1\d{2}|2[0-4]\d|[1-9]?\d|25[0-5])\b
Pattern Demo (in PHP/PCRE to show step count)
4010 steps when checking a list from 0 to 256.
This pattern will not match 01 or 001. (no match on one or more leading zeros)
Considerations:
Use quantifiers on consecutive duplicate characters.
Organize the alternatives not in sequential order (single-digit, double-digit, 100's, under-249, 250-255) but with quickest mis-matches first.
Avoid non-essential capture (or non-capture) groups. (despite seeming logical to condense the "two hundreds" portion of the pattern)

Please try this
"^(((\d|0\d|00\d|\d{2}|0\d{2}|1\d{2}|2[0-4]\d|2[0-5]{2})\.){3})(\d|0\d|00\d|\d{2}|0\d{2}|1\d{2}|2[0-4]\d|2[0-5]{2})$"
It works also with leading zeroes

boolean valid = IP.matches("(0?[0-9]{1,2}|1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])");

Complete ip inet4 match :
JS
/(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])/g.exec(myIp);
https://regex101.com/r/tU3gC3/12
Minified :
/(1?(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])/g.exec(myIp);
https://regex101.com/r/tU3gC3/13

This will work for following pattern and ip containing initial zeros
e.g: 023.45.12.56
pattern=(\\d{1,2}|(0|1)\\d{2}|2[0-4]\\d|25[0-5]);

If you need leading zeros, try this:
"((\\d{1,2}|[01]\\d{1,2}|[0-2][0-4]\\d|25[0-5])\\.){3}(\\d{1,2}|[01]\\d{1,2}|[0-2][0-4]\\d|25[0-5])"
It satisfies following conditions: IP address is a string in the form "A.B.C.D", where the value of A, B, C, and D may range from 0 to 255. Leading zeros are allowed. The length of A, B, C, or D can't be greater than 3.
Maybe somebody can help with additional simplifying?

If you want to validate ip4 with 'ip/mask', so regex looks like this:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[1-2][0-9]|3[0-2]))$
Just ip
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
JS code to test it
function isMatchByRegexp(stringToValidate, regexp) {
var re = new RegExp(regexp);
return re.test(stringToValidate);
}

(2[0-4][0-9])|([0-1]?[0-9]?[0-9])
To match 0 to 249 specifically

You can simplify it by thinking in four conditions that might happen
String zeroTo255 = "((0|1)\\d{2}|2[0-4]\\d|25[0-5]|\\d{1,2})";
String validIpPattern = zeroTo255 + "\\." + zeroTo255 + "\\." + zeroTo255 + "\\." + zeroTo255;
(0|1)\d{2} catches any three digit number starting with 0 or 1.
2[0-4]\d catches numbers between 200 and 249.
25[0-5] catches numbers between 250 and 255.
\d{1,2} catches any one or two digit number
you can test it in https://regexr.com/
To test it here in regexr you need to remove one backslash
(\\d --> \d)
((0|1)\d{2}|2[0-4]\d|25[0-5]|\d{1,2})
Note that \d represents digits in regular expressions, same as [0-9]

Related

Extract exactly n digits in a sentence using REGEX

Example
The no.s 1234 65
Input: n
For n=4, the output should be 1234
For n=2, the output should be : 65 (not 12)
Tried \d{n} which gives 12 and \d{n,} gives 1234 but i want the exact matching one.
Pattern p = Pattern.compile("//\d{n,}");
you need negative lookaround assertion: (?<!..): negative look behind, and (?!..): negative look ahead : regex101
(?<!\d)\d{4}(?!\d)
however not all regex engine supports them, maybe a work around may match also the preceeding character and following character (contrary to look-around which are 0 width matches), (\D matches all excpet a digit)
(?:^|\D)(\d{4})(?:\D|$)
I think what you meant is the \b character.
Hence, the regex you're looking for would be (for n=2):
\b\d{2}\b
From what I understand, you're looking for a regex that will match a number in a string which has n digits, taking into into account the spacing between the numbers. If that's the case, you're looking for something like this:
\b\d{4}\b
The \b will ensure the match is constrained to the start/end of a 'word' where a word is the boundary between anything matched by \w (which includes digits) and anything matched by the opposite, \W (which includes spaces).
I don't code in java but I can try to answer this using regex in general.
If your number is in the format d1d2d3d4 d5d6 and you want to extract digits d5d6, create 3 groups as r'([0-9]+)("/s")([0-9]+)' – each set of parenthesis () represent one group. Now, extract the third group only in another object which is your required output.

parsing numerical address

I have been trying to parse a numerical address from a string using regex.
So far, I have been able to successfully get the numerical address (partially) 63.88.73.26:80 from the string http://63.88.73.26:80/. However I have been trying to skip over the :80/, and have had no luck.
What I have tried so far is:
Pattern.compile("[0-999].*[0-999][\\p{Digit}]", Pattern.DOTALL);
however does still includes :80
I dont know what I am missing here, I have tried to check for \p{Digit} at the end, but that doesn't do much either
Thanks for your time!
You are looking for a positive look ahead (?=...). This will match only if it is followed by a specific expression, the one in the positive look ahead's parenthesis. In it's simplest form you could have
[0-9\.]+(?=:[0-9]{0,4})
Though you may want to change the [0-9\.]+ part (match 1 or more digit or full stop) with something more complete to check that you have a properly formed address
Check out regexr.com where you can fiddle your expression to your heart's content until it works...
Note that Pshemo indicated the right approach with URL and getHost():
Gets the host name of this URL, if applicable. The format of the host conforms to RFC 2732, i.e. for a literal IPv6 address, this method will return the IPv6 address enclosed in square brackets ('[' and ']').
Thus, it is best to use the proper tool here:
import java.net.*;
....
String str = new URL("http:" + "//63.88.73.26:80/").getHost();
System.out.println(str); // => 63.88.73.26
See the Java demo
You mention that you want to learn regex, so let's inspect your pattern:
[0-999] - matches any 1 digit, a single digit (0-9 creates a range that matches 0..9, and the two 9s are redundant and can be removed)
.* - any 0+ chars, greedily, i.e. up to the last...
[0-999] - see above (any 1 digit)
[\\p{Digit}] - any Unicode digit
That means, you match a string starting with a digit and up to the last occurrence of 2 consecutive digits.
You need a sequence of digits and dots. There are multiple ways to extract such strings.
Using verbose pattern with exact character specification together with how many occurrences you need: [0-9]{1,3}(?:\.[0-9]{1,3}){3} (the whole match - matcher.group() - holds the required value).
Using the "brute-force" character class approach (see Jonathan's answer), but I'd use a capturing group instead of a lookahead and use an unescaped dot since inside a character class it is treated as a literal dot: ([0-9.]+):[0-9] (now, the value is in matcher.group(1))
A "fancy" "get-string-between-two-strings" approach: all text other than : and / between http:// and : must be captured into a group - https?://([^:/]+): (again, the value is in matcher.group(1))
Some sample code (Approach #1):
Pattern ptrn = Pattern.compile("[0-9]{1,3}(?:\\.[0-9]{1,3}){3}");
Matcher matcher = ptrn.matcher("http://63.88.73.26:80/");
if (matcher.find()) {
System.out.println(matcher.group());
}
Must read: Character Classes or Character Sets.

Regex: How to find exact value length?

I got these several cases of given String:
key1=12345
key1=12345&key2=12345
key1=12345123456789
key1=12345123456789&key2=123456789
Using this pattern: (key1)=([^&]{5})(|$)).
The expected results are:
12345
12345, 12345
nothing
nothing
And while running, the results were:
12345
12345, 12345
12345
12345, 12345
Which means that the {5} is actually cutting the text by the given length which is 5 and not looking for exact 5.
How can I make it to look for exact 5 and not to cut the text ?
This pattern will do it:
=([^&]{5})(?:&|$)
It finds =, followed by 5 captured characters that are not &, immediately be followed by either & or the end of the string.
Test
public static void main(String[] args) {
test("key1=12345");
test("key1=12345&key2=12345");
test("key1=12345123456789");
test("key1=12345123456789&key2=123456789");
}
private static void test(String input) {
Matcher m = Pattern.compile("=([^&]{5})(?:&|$)").matcher(input);
List<String> list = new ArrayList<>();
while (m.find())
list.add(m.group(1));
System.out.println(list);
}
Output
[12345]
[12345, 12345]
[]
[]
([^=&]+)=(?<![^=&])([^=&]{5})(?![^=&])
key, then =, then five characters that are not = or &, not surrounded by more characters that are not = or &. (\b is useful in limited circumstances where your values are guaranteed to only consist of letters, numbers and underscores; negative lookaround is much more general).
Basically, you must add boundaries somehow. One can use anchors for that (such as \b for "word boundary", or ^ and $ for string/line boundary). Other way is to limit match until a given character appears - e.g [^&\n] - not until the & sign or a newline, then check the length programmaticaly in Java.
I came up with a regex of my own: demo here
(?:=)(\d{5})(?:[&|\n])
First of all I look for a = sign, but do not capture it.
Then I look for 5 digits...
... followed either by & sign or a newline (which I do not capture either)
If you need to look only for key1, key2 values, just add (?:key\d=) instead of (?:=) - demo
Then the only matches found are of given length.
#Stribizhev's regex might be potentially more secure and more false-positive protected, though.

Java Regex of String start with number and fixed length

I made a regular expression for checking the length of String , all characters are numbers and start with number e.g 123
Following is my expression
REGEX =^123\\d+{9}$";
But it was unable to check the length of String. It validates those strings only their length is 9 and start with 123.
But if I pass the String 1234567891 it also validates it. But how should I do it which thing is wrong on my side.
Like already answered here, the simplest way is just removing the +:
^123\\d{9}$
or
^123\\d{6}$
Depending on what you need exactly.
You can also use another, a bit more complicated and generic approach, a negative lookahead:
(?!.{10,})^123\\d+$
Explanation:
This: (?!.{10,}) is a negative look-ahead (?= would be a positive look-ahead), it means that if the expression after the look-ahead matches this pattern, then the overall string doesn't match. Roughly it means: The criteria for this regular expression is only met if the pattern in the negative look-ahead doesn't match.
In this case, the string matches only if .{10} doesn't match, which means 10 or more characters, so it only matches if the pattern in front matches up to 9 characters.
A positive look-ahead does the opposite, only matching if the criteria in the look-ahead also matches.
Just putting this here for curiosity sake, it's more complex than what you need for this.
Try using this one:
^123\\d{6}$
I changed it to 6 because 1, 2, and 3 should probably still count as digits.
Also, I removed the +. With it, it would match 1 or more \ds (therefore an infinite amount of digits).
Based on your comment below Doorknobs's answer you can do this:
int length = 9;
String prefix = "123"; // or whatever
String regex = "^" + prefix + "\\d{ " + (length - prefix.length()) + "}$";
if (input.matches(regex)) {
// good
} else {
// bad
}

Java: Change an var's value (String) according to the value of an regex

I would like to know if it is possible (and if possible, how can i implement it) to manipulate an String value (Java) using one regex.
For example:
String content = "111122223333";
String regex = "?";
Expected result: "1111 2222 3333 ##";
With one regex only, I don't think it is possible. But you can:
first, replace (?<=(.))(?!\1) with a space;
then, use a string append to append " ##".
ie:
Pattern p = Pattern.compile("(?<=(.))(?!\\1)");
String ret = p.matcher(input).replaceAll(" ") + " ##";
If what you meant was to separate all groups, then drop the second operation.
Explanation: (?<=...) is a positive lookbehind, and (?!...) a negative lookahead. Here, you are telling that you want to find a position where there is one character behind, which is captured, and where the same character should not follow. And if so, replace with a space. Lookaheads and lookbehinds are anchors, and like all anchors (including ^, $, \A, etc), they do not consume characters, this is why it works.
OK, since the OP has redefined the problem (ie, a group of 12 digits which should be separated in 3 groups of 4, then followed by ##, the solution becomes this:
Pattern p = Pattern.compile("(?<=\\d)(?=(?:\\d{4})+$)");
String ret = p.matcher(input).replaceAll(" ") + " ##";
The regex changes quite a bit:
(?<=\d): there should be one digit behind;
(?=(?:\d{4})+$): there should be one or more groups of 4 digits afterwards, until the end of line (the (?:...) is a non capturing grouping -- not sure it really makes a difference for Java).
Validating that the input is 12 digits long can easily be done with methods which are not regex-related at all. And this validation is, in fact, necessary: unfortunately, this regex will also turn 12345 into 1 2345, but there is no way around that, for the reason that lookbehinds cannot match arbitrary length regexes... Except with the .NET languages. With them, you could have written:
(?<=^(?:\d{4})+)(?=(?:\d{4})+$

Categories

Resources