Java exception pattern - java

I'm trying to write a code for exception.
If the input does not match with the pattern below (this is just example) it will throw an exception message.
8454T3477-90
This is the code that I came up with. However, I'm not sure if this is the right patter...
public void setLegalDescription(String legalDescription) throws MyInvalidLegalDescriptionException
{
String valid = ("[0-9999][A-Z][0-9999]-[0-99]");
if (!legalDescription.matches(valid))
{
//throw new MyInvalidLegalDescriptionException("Invalid format! Should be " + "e.g 4050F8335-14");
}
this.legalDescription = legalDescription;
}

Your pattern is slightly off. Try this version:
String valid = ("[0-9]{4}[A-Z][0-9]{4}-[0-9]{2}");
if (!legalDescription.matches(valid))
{
// throw new MyInvalidLegalDescriptionException("Invalid format! Should be " + "e.g 4050F8335-14");
}
An explanation of the regex:
[0-9]{4} any 4 digits
[A-Z] any capital letter
[0-9]{4} any 4 digits
- a dash
[0-9]{2} any 2 digits
It should be noted that [0-9999] does not match any number between 0 and 9999. Rather, it actually just matches a single digit between 0 and 9.
If the width of your identifier is not fixed, then perhaps use this pattern:
[0-9]{1,4}[A-Z][0-9]{1,4}-[0-9]{1,2}

Related

Why does this regex fails to check accurately?

I have the following regex method which does the matches in 3 stages for a given string. But for some reason the Regex fails to check some of the things. As per whatever knowledge I have gained by working they seem to be correct. Can someone please correct me what am I doing wrong here?
I have the following code:
public class App {
public static void main(String[] args) {
String identifier = "urn:abc:de:xyz:234567.1890123";
if (identifier.matches("^urn:abc:de:xyz:.*")) {
System.out.println("Match ONE");
if (identifier.matches("^urn:abc:de:xyz:[0-9]{6,12}.[0-9]{1,7}.*")) {
System.out.println("Match TWO");
if (identifier.matches("^urn:abc:de:xyz:[0-9]{6,12}.[a-zA-Z0-9.-_]{1,20}$")) {
System.out.println("Match Three");
}
}
}
}
}
Ideally, this code should generate the output
Match ONE
Match TWO
Match Three
Only when the identifier = "urn:abc:de:xyz:234567.1890123.abd12" but it provides the same output event if the identifier does not match the regex such as for the following inputs:
"urn:abc:de:xyz:234567.1890123"
"urn:abc:de:xyz:234567.1890ANC"
"urn:abc:de:xyz:234567.1890123"
"urn:abc:de:xyz:234567.1890ACB.123"
I am not understanding why is it allowing the Alphanumeric characters after the . and also it does not care about the characters after the second ..
I would like my Regex to check that the string has the following format:
String starts with urn:abc:de:xyz:
Then it has the numbers [0-9] which range from 6 to 12 (234567).
Then it has the decimal point .
Then it has the numbers [0-9] which range from 1 to 7 (1890123)
Then it has the decimal point ..
Finally it has the alphanumeric character and spcial character which range from 1 to 20 (ABC123.-_12).
This is an valid string for my regex: urn:abc:de:xyz:234567.1890123.ABC123.-_12
This is an invalid string for my regex as it misses the elements from point 6:
urn:abc:de:xyz:234567.1890123
This is also an invalid string for my regex as it misses the elements from point 4 (it has ABC instead of decimal numbers).
urn:abc:de:xyz:234567.1890ABC.ABC123.-_12
This part of the regex:
[0-9]{6,12}.[0-9]{1,7} matches 6 to 12 digits followed by any character followed by 1 to 7 digits
To match a dot, it needs to be escaped. Try this:
^urn:abc:de:xyz:[0-9]{6,12}\.[0-9]{1,7}\.[a-zA-Z0-9\-_]{1,20}$
This will match with any number of dot alphanum at the end of the string as your examples:
^urn:abc:de:xyz:\d{6,12}\.\d{1,7}(?:\.[\w-]{1,20})+$
Demo & explanation

Check if String has specific repetitive special characters only

I have a string of format ^%^%^%^%. I need to check if the string has nothing other than repetitive patterns of ^%
For example
1. ^%^%^%^% > Valid
2. ^%^%aa^%^% > Invalid
3. ^%^%^%^%^%^% > Valid
4. ^%^%^^%^% > Invalid
5. %^%^%^%^% > Invalid
How do I do this in Java?
I tried :
String text = "^%^%^%^%^%";
if (Pattern.matches(("[\\^\\%]+"), text)==true) {
System.out.println("Valid");
} else {
System.out.println("Invalid");
}
However it gives me Valid for cases 4 and 5.
In your pattern you use a character class which matches only 1 of the listed characters and then repeats that 1+ times.
You could use that ^ to anchor the start of the string and end with $ to assert the end of the string.
Then repeat 1+ times matching \\^%
^(?:\\^%)+$
Regex demo
Try this pattern ^(?:\^%)+$
Explanation:
^ - match beginning of the string
(?:...) - non-capturing group
\^% - match ^% literally
(?:\^%)+ - match ^% one or more times
$ - match end of the string
Demo
You can simply do:
if (str.replace("^%", "").isEmpty()) {
…
}
The replace method replaces the string as often as possible, therefore it fits exactly what you need.
It also matches the empty string, which, according to the specification, "contains nothing else than this pattern". In cases like these, you should always ask whether the empty string is meant as well.
String[] text = {"^%^%^%^%","^%^%aa^%^%","^%^%^%^%^%^%","^%^%^^%^%","%^%^%^%^%" };
for (String t: text) {
if(Pattern.matches(("[\\^\\%]+[a-z]*[a-z]*[(\\^\\%)]+"), t)==true) {
System.out.println("Valid");
} else {
System.out.println("Invalid");
}
}

Use regex to un camelCase Java String

This code seems to work perfectly, but I'd love to clean it up with regex.
public static void main(String args[]) {
String s = "IAmASentenceInCamelCaseWithNumbers500And1And37";
System.out.println(unCamelCase(s));
}
public static String unCamelCase(String string) {
StringBuilder newString = new StringBuilder(string.length() * 2);
newString.append(string.charAt(0));
for (int i = 1; i < string.length(); i++) {
if (Character.isUpperCase(string.charAt(i)) && string.charAt(i - 1) != ' '
|| Character.isDigit(string.charAt(i)) && !Character.isDigit(string.charAt(i - 1))) {
newString.append(' ');
}
newString.append(string.charAt(i));
}
return newString.toString();
}
Input:
IAmASentenceInCamelCaseWithNumbers500And1And37
Output:
I Am A Sentence In Camel Case With Numbers 500 And 1 And 37
I'm not a fan of using that ugly if statement, and I'm hoping there's a way to use a single line of code that utilizes regex. I tried for a bit but it would fail on words with 1 or 2 letters.
Failing code that doesn't work:
return string.replaceAll("(.)([A-Z0-9]\\w)", "$1 $2");
The right regex and code to do your job is this.
String s = "IAmASentenceInCamelCaseWithNumbers500And1And37";
System.out.println("Output: " + s.replaceAll("[A-Z]|\\d+", " $0").trim());
This outputs,
Output: I Am A Sentence In Camel Case With Numbers 500 And 1 And 37
Editing answer for query asked by OP in comment:
If input string is,
ThisIsAnABBRFor1Abbreviation
Regex needs a little modification and becomes this, [A-Z]+(?![a-z])|[A-Z]|\\d+ for handling abbreviation.
This code,
String s = "ThisIsAnABBRFor1Abbreviation";
System.out.println("Input: " + s.replaceAll("[A-Z]+(?![a-z])|[A-Z]|\\d+", " $0").trim());
Gives expected output as per OP ZeekAran in comment,
Input: This Is An ABBR For 1 Abbreviation
You may use this lookaround based regex solution:
final String result = string.replaceAll(
"(?<=\\S)(?=[A-Z])|(?<=[^\\s\\d])(?=\\d)", " ");
//=> I Am A Sentence In Camel Case With Numbers 500 And 1 And 37
RegEx Demo
RegEx Details:
Regex matches either of 2 conditions and replaces it with a space. It will ignore already present spaces in input.
(?<=\\S)(?=[A-Z]): Previous char is non-space and next char is a uppercase letter
|: OR
(?<=[^\\s\\d])(?=\\d): previous char is non-digit & non-space and next one is a digit
I think you can try this
let str = "IAmASentenceInCamelCaseWithNumbers500And1And37";
function unCamelCase(str){
return str.replace(/(?:[A-Z]|[0-9]+)/g, (m)=>' '+m.toUpperCase()).trim();
}
console.log(unCamelCase(str));
Explanation
(?:[A-Z]|[0-9]+)
?: - Non capturing group.
[A-Z] - Matches any one capital character.
'|' - Alternation (This works same as Logical OR).
[0-9]+ - Matches any digit from 0-9 one or more time.
P.S Sorry for the example in JavaScript but same logic can be achived in JAVA pretty easily.

Regular Expression to match spaces between numbers and operators but no spaces between numbers

I've searched many post on this forum and to my surprise, I haven't found anyone with a problem like mine.
I have to make a simple calculator for string values from console. Right now,I'm trying to make some regexes to validate the input.
My calculator has to accept numbers with spaces between the operators (only + and - is allowed) but not the ones with spaces between numbers, to sum up:
2 + 2 = 4 is correct, but
2 2 + 2 --> this should make an error and inform user on the console that he put space between numbers.
I've come up with this:
static String properExpression = "([0-9]+[+-]?)*[0-9]+$";
static String noInput = "";
static String numbersFollowedBySpace = "[0-9]+[\\s]+[0-9]";
static String numbersWithSpaces = "\\d+[+-]\\d+";
//I've tried also "[\\d\\s+\\d]";
void validateUserInput() {
Scanner sc = new Scanner(System.in);
System.out.println("Enter a calculation.");
input = sc.nextLine();
if(input.matches(properExpression)) {
calculator.calculate();
} else if(input.matches(noInput)) {
System.out.print(0);
} else if(input.matches(numbersFollowedBySpace)) {
input.replaceAll(" ", "");
calculator.calculate();
} else if(input.matches(numbersWithSpaces))
{
System.out.println("Check the numbers.
It seems that there is a space between the digits");
}
else System.out.println("sth else");
Can you give me a hint about the regex I should use?
To match a complete expression, like 2+3=24 or 6 - 4 = 2, a regex like
^\d+\s*[+-]\s*\d+\s*=\s*\d+$
will do. Look at example 1 where you can play with it.
If you want to match longer expressions like 2+3+4+5=14 then you can use:
^\d+\s*([+-]\s*\d+\s*)+=\s*\d+$
Explanation:
^\d+ # first operand
\s* # 0 or more spaces
( # start repeating group
[+-]\s* # the operator (+/-) followed by 0 or more spaces
\d+\s* # 2nd (3rd,4th) operand followed by 0 or more spaces
)+ # end repeating group. Repeat 1 or more times.
=\s*\d+$ # equal sign, followed by 0 or more spaces and result.
Now, you might want to accept an expression like 2=2 as a valid expression. In that case the repeating group could be absent, so change + into *:
^\d+\s*([+-]\s*\d+\s*)*=\s*\d+$
Look at example 2 for that one.
Try:
^(?:\d+\s*[+-])*\s*\d+$
Demo
Explanation:
The ^ and $ anchor the regex to match the whole string.
I have added \s* to allow whitespace between each number/operator.
I have replaced [0-9] with \d just to simplify it slightly; the two are equivalent.
I'm a little unclear whether you wanted to allow/disallow including = <digits> at the end, since your question mentions this but your attempted properExpression expression doesn't attempt it. If this is the case, it should be fairly easy to see how the expression can be modified to support it.
Note that I've not attempted to solve any potential issues arising out of anything other than regex issues.
Tried as much as possible to keep your logical flow. Although there are other answers which are more efficient but you would've to alter your logical flow a lot.
Please see the below and let me know if you have any questions.
static String properExpression = "\\s*(\\d+\\s*[+-]\\s*)*\\d+\\s*";
static String noInput = "";
static String numbersWithSpaces = ".*\\d[\\s]+\\d.*";
//I've tried also "[\\d\\s+\\d]";
static void validateUserInput() {
Scanner sc = new Scanner(System.in);
System.out.println("Enter a calculation.");
String input = sc.nextLine();
if(input.matches(properExpression)) {
input=input.replaceAll(" ", ""); //You've to assign it back to input.
calculator.calculate(); //Hope you have a way to pass input to calculator object
} else if(input.matches(noInput)) {
System.out.print(0);
} else if(input.matches(numbersWithSpaces)) {
System.out.println("Check the numbers. It seems that there is a space between the digits");
} else
System.out.println("sth else");
Sample working version here
Explanation
The below allows replaceable spaces..
\\s* //Allow any optional leading spaces if any
( //Start number+operator sequence
\\d+ //Number
\\s* //Optional space
[+-] //Operator
\\s* //Optional space after operator
)* //End number+operator sequence(repeated)
\\d+ //Last number in expression
\\s* //Allow any optional space.
Numbers with spaces
.* //Any beginning expression
\\d //Digit
[\\s]+ //Followed by one or more spaces
\\d //Followed by another digit
.* //Rest of the expression

Regex to get first number in string with other characters

I'm new to regular expressions, and was wondering how I could get only the first number in a string like 100 2011-10-20 14:28:55. In this case, I'd want it to return 100, but the number could also be shorter or longer.
I was thinking about something like [0-9]+, but it takes every single number separately (100,2001,10,...)
Thank you.
/^[^\d]*(\d+)/
This will start at the beginning, skip any non-digits, and match the first sequence of digits it finds
EDIT:
this Regex will match the first group of numbers, but, as pointed out in other answers, parseInt is a better solution if you know the number is at the beginning of the string
Try this to match for first number in string (which can be not at the beginning of the string):
String s = "2011-10-20 525 14:28:55 10";
Pattern p = Pattern.compile("(^|\\s)([0-9]+)($|\\s)");
Matcher m = p.matcher(s);
if (m.find()) {
System.out.println(m.group(2));
}
Just
([0-9]+) .*
If you always have the space after the first number, this will work
Assuming there's always a space between the first two numbers, then
preg_match('/^(\d+)/', $number_string, $matches);
$number = $matches[1]; // 100
But for something like this, you'd be better off using simple string operations:
$space_pos = strpos($number_string, ' ');
$number = substr($number_string, 0, $space_pos);
Regexs are computationally expensive, and should be avoided if possible.
the below code would do the trick.
Integer num = Integer.parseInt("100 2011-10-20 14:28:55");
[0-9] means the numbers 0-9 can be used the + means 1 or more times. if you use [0-9]{3} will get you 3 numbers
Try ^(?'num'[0-9]+).*$ which forces it to start at the beginning, read a number, store it to 'num' and consume the remainder without binding.
This string extension works perfectly, even when string not starts with number.
return 1234 in each case - "1234asdfwewf", "%sdfsr1234" "## # 1234"
public static string GetFirstNumber(this string source)
{
if (string.IsNullOrEmpty(source) == false)
{
// take non digits from string start
string notNumber = new string(source.TakeWhile(c => Char.IsDigit(c) == false).ToArray());
if (string.IsNullOrEmpty(notNumber) == false)
{
//replace non digit chars from string start
source = source.Replace(notNumber, string.Empty);
}
//take digits from string start
source = new string(source.TakeWhile(char.IsDigit).ToArray());
}
return source;
}
NOTE: In Java, when you define the patterns as string literals, do not forget to use double backslashes to define a regex escaping backslash (\. = "\\.").
To get the number that appears at the start or beginning of a string you may consider using
^[0-9]*\.?[0-9]+ # Float or integer, leading digit may be missing (e.g, .35)
^-?[0-9]*\.?[0-9]+ # Optional - before number (e.g. -.55, -100)
^[-+]?[0-9]*\.?[0-9]+ # Optional + or - before number (e.g. -3.5, +30)
See this regex demo.
If you want to also match numbers with scientific notation at the start of the string, use
^[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Just number
^-?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Number with an optional -
^[-+]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Number with an optional - or +
See this regex demo.
To make sure there is no other digit on the right, add a \b word boundary, or a (?!\d)
or (?!\.?\d) negative lookahead that will fail the match if there is any digit (or . and a digit) on the right.
public static void main(String []args){
Scanner s=new Scanner(System.in);
String str=s.nextLine();
Pattern p=Pattern.compile("[0-9]+");
Matcher m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" ");
}
\d+
\d stands for any decimal while + extends it to any other decimal coming directly after, until there is a non number character like a space or letter

Categories