I'm trying to do a simple validation for vehicle registration number.
It must include "-" Dash/Hyphen symbol. Example: BIR - 5698
It allows Numbers/Letters and Hyphen symbol only.
All the other symbols are invalid. ( `~!##$%^&*()_+=./;,<>":|[]{} )
My code -
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
if (in.hasNext("[A-Za]")) {
System.out.println("Vehicles :" + vehicles );
}else {
System.out.println("Enter a Valid Value");
Thank you. Your kind help highly appreciated.
I'm not sure if what you show as an example registration number is the actual format for a vehicle registration number (3 chars, a dash, 4 chars). Does the whitespace before and after the dash need to be there or is that optional? Are there only three alphanumeric characters before the dash and always 4 alphanumeric character after the dash? Because you haven't indicated as such either way I'm going to assume so. The supplied Regular Expression below can be easily modified to accommodate whatever format(s) are required.
Here is the code:
String ls = System.lineSeparator();
Scanner in = new Scanner(System.in);
String vrn = "";
while (vrn.isEmpty()) {
System.out.print("Please enter a valid Vehicle Registration number" + ls
+ "or 'q' to quit: -> ");
vrn = in.nextLine().trim();
if (vrn.equalsIgnoreCase("Q")) { //Quit?
return;
}
// Validate entry...
if (!vrn.matches("(?i)[A-Z0-9]{3} ?\\- ?[A-Z0-9]{4}")) {
System.out.println("Invalid Vehicle Registation Number! ("
+ vrn + ") Try again..." + ls);
vrn = ""; // Empty vrn so to re-loop.
}
}
System.out.println("VALID VRN!");
About the Regular Expression (regex):
(?i) Letter case insensitive;
[A-Z0-9]{3} Any 3 alphanumeric character (A to Z, a to z, or 0 to 9) before the dash;
? An optional single whitespace before the mandatory dash (-);
\\- A mandatory single literal Dash character;
? An optional single whitespace after the mandatory dash (-);
[A-Z0-9]{4} Any 4 alphanumeric characters (A to Z, a to z, or 0 to 9) after the dash;
If you want to change the number of allowable characters within the regex then you can consider any one of these few examples:
{3} Strictly 3 characters allowed only;
{3,6} Strictly 3 to 6 characters allowed only;
{3,} 3 or more characters allowed;
`{0,} 0 or more characters allowed.
Add all valid characters:
if (in.hasNext("[A-Za-z0-9\-]")) {
Related
So I'm supposed to use the scanner to read the users employee number and then put that into a method that returns a boolean value. The employee is supposed to have the form DDDDD-LDDDD with the d being digits and l being letters. If the input matches this format I'm supposed to inform the user that they have a valid number and if it doesn't then I have to say it's invalid. I've trying to separate into two substrings to be able to see if they contain digits as well as to see if it contains a letter. I then try to combine these using a loop and if it's in that format the user is told it's valid and if it's not they are informed it's not. Is there any other possible way to check and see if the employee number is composed of digits besides obviously the dash and letter that I can then use to prompt the user if what they wrote is valid? This is only written in Java
You can use regular expressions:
final String[] strings = {
"54321-A1234", // A valid employee ID
"012948B9832", // The dash is replaced with a number
"39832-30423", // The letter is replaced with a number
"24155-C90320", // A valid employee ID but the last number
};
for (String string : strings) {
if (string.matches("[0-9]{5}-[A-Za-z]{1}[0-9]{4}")) {
System.out.println("The string " + string + " is a valid pattern.");
} else {
System.out.println("The string " + string + " is an invalid pattern.");
}
}
This will output
The string 54321-A1234 is a valid pattern.
The string 012948B9832 is an invalid pattern.
The string 39832-30423 is an invalid pattern.
The string 24155-C90320 is an invalid pattern.
Explanation:
[0-9]{5} means "match exactly five digits";
- means "match the character - exactly one time";
[A-Za-z]{1} means "match exactly one letter, case-insensitive";
[0-9]{4} means "match exactly four digits";
Note that [0-9] can be replaced with \\d and that {1} is optional, but I've added just for explicitness.
You can do it with a regular expression. This prompts for the string and if not in proper format, reprompts.
Scanner input = new Scanner(System.in);
String str = null;
System.out.println("Please enter string in DDDDD-LDDDD format");
while (true) {
str = input.nextLine();
// checks for 5 digits followed by - one letter and four digits.
if(str.matches("\\d{5}-\\p{Alpha}\\d{4}")) {
break;
}
System.out.println("Please try again!");
}
System.out.println(str + " is a valid string");
I must create a java program to check if the password is valid or not based on these conditions:
to be at least 5 chars long or at most 12 chars long
to start with an uppercase letter
to end with two different digits
to include at least one special character from the following: ! " # $ % & ' ( ) * + -
to include at least one lowercase letter
This is what I have written so far, and I want to know what's the regular expression to check the second condition (that the password must end with 2 different digits) ?
import java.util.Scanner;
public class PasswordValidation {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter a password");
String password = sc.next();
if (isValid(password)) {
System.out.println("OK");
} else {
System.out.println("NO");
}
}
public static boolean isValid (String password) {
return password.matches ("^[A-Z](?=.*[a-z])(?=.*[!#$%&'()+-]).{5,12}$");
}
}
Try using this regex pattern:
^(?=.*[a-z])(?=.*[!"#$%&'()*+-])[A-Z].{2,9}(\d)(?!\1)\d$
Java code:
String password = "Apple$123";
if (password.matches("(?=.*[a-z])(?=.*[!\"#$%&'()*+-])[A-Z].{2,9}(\\d)(?!\\1)\\d")) {
System.out.println("MATCH");
}
This prints MATCH.
Here is an explanation of the regex pattern:
^ from the start of the password
(?=.*[a-z]) assert that a lowercase letter be present
(?=.*[!"#$%&'()*+-]) assert that a special character be present
[A-Z] password starts with uppercase letter
.{2,9} followed by any 2 to 9 characters (total 5 to 12)
(\d) 2nd to last character is any digit
(?!\1)\d last character is any digit other than previous one
$ end of the password
I have a function that takes a scanner of a text file as input, and I need to extract integer values from each line. These lines might not follow a rigid syntax.
I have tried to to use skip() to ignore specific non-integers, but I fear I may be using it for something it's not capable of.
I've also tried turning the token into a string and using replaceAll(";", ""), but that quickly turns my code into a mess of if statements and String to int conversions. It gets bad quite fast considering I have a lot of different variables that need to be set here.
Is there is a more elegant solution?
Here is my input file:
pop 25; // my code must accept this
pop 25 ; // and also this
house 3.2, 1; // some lines will set multiple values
house 3.2 , 1 ; // so I will need to ignore both commas and semicolons
Here is my code:
static int population = -1;
static double median = -1;
static double scatter = -1;
private static void readCommunity(Scanner sc) {
while (sc.hasNext()) {
String input = sc.next();
if ("pop".equals(input)) {
sc.skip(";*"); // my guess is this wouldn't work unless the
// token had a ';' BEFORE the integer
if (sc.hasNextInt()) {
population = sc.nextInt();
} else { // throw an error. not important here }
sc.nextLine();
} else if ("house".equals(input)) {
sc.skip(",*");
if (sc.hasNextDouble()) {
median = sc.nextDouble;
sc.skip(";*");
if (sc.hasNextDouble()) {
scatter = sc.nextDouble();
} else { // error }
} else { // error }
sc.nextLine();
}
}
}
In my opinion, I think it's just easier to read each entire file data line then split that line into what I need, and do validations on the read in data values, etc. For example:
private static void readCommunity(String dataFilePath) {
File file = new File(dataFilePath);
if (!file.exists()) {
System.err.println("File Not Found! (" + dataFilePath + ")");
return;
}
int lineCount = 0; // For counting file lines.
// 'Try With Resources' used here so as to auto-close reader.
try (Scanner sc = new Scanner(file)) {
while (sc.hasNextLine()) {
String fileInput = sc.nextLine().trim();
lineCount++; // Increment line counter.
// Skip blank lines (if any).
if (fileInput.isEmpty()) {
continue;
}
/* Remove comments from data line (if any). Your file
example shows comments at the end of each line. Yes,
I realize that your file most likely doesn't contain
these but it doesn't hurt to have this here in case
it does or if you want to have that option. Comments
can start with // or /*. Comments must be at the end
of a data line. This 'does not' support any Multi-line
comments. More code is needed for that. */
if (fileInput.contains("//") || fileInput.contains("/*")) {
fileInput = fileInput.substring(0, fileInput.contains("//")
? fileInput.indexOf("//") : fileInput.indexOf("/*"));
}
// Start parsing the data line into required parts...
// Start with semicolon portions
String[] lineMainParts = fileInput.split("\\s{0,};\\s{0,}");
/* Iterate through all the main elemental parts on a
data line (if there is more than one), for example:
pop 30; house 4.3, 1; pop 32; house 3.3, 2 */
for (int i = 0; i < lineMainParts.length; i++) {
// Is it a 'pop' attribute?
if (lineMainParts[i].toLowerCase().startsWith("pop")) {
//Yes it is... so validate, convert, and display the value.
String[] attributeParts = lineMainParts[i].split("\\s+");
if (attributeParts[1].matches("-?\\d+|\\+?\\d+")) { // validate string numerical value (Integer).
population = Integer.valueOf(attributeParts[1]); // convert to Integer
System.out.println("Population:\t" + population); // display...
}
else {
System.err.println("Invalid population value detected in file on line "
+ lineCount + "! (" + lineMainParts[i] + ")");
}
}
// Is it a 'house' attribute?
else if (lineMainParts[i].toLowerCase().startsWith("house")) {
/* Yes it is... so split all comma delimited attribute values
for 'house', validate each numerical value, convert each
numerical value, and display each attribute and their
respective values. */
String[] attributeParts = lineMainParts[i].split("\\s{0,},\\s{0,}|\\s+");
if (attributeParts[1].matches("-?\\d+(\\.\\d+)?")) { // validate median string numerical value (Double or Integer).
median = Double.valueOf(attributeParts[1]); // convert to Double.
System.out.println("Median: \t" + median); // display median...
}
else {
System.err.println("Invalid Median value detected in file on line "
+ lineCount + "! (" + lineMainParts[i] + ")");
}
if (attributeParts[2].matches("-?\\d+|\\+?\\d+")) { // validate scatter string numerical value (Integer).
scatter = Integer.valueOf(attributeParts[2]); // convert to Integer
System.out.println("Scatter: \t" + scatter); // display scatter...
}
else {
System.err.println("Invalid Scatter value detected in file on line "
+ lineCount + "! (" + lineMainParts[i] + ")");
}
}
else {
System.err.println("Unhandled Data Attribute detected in data file on line " + lineCount + "! ("
+ lineMainParts[i] + ")");
}
}
}
}
catch (FileNotFoundException ex) {
System.err.println(ex);
}
}
There are several Regular Expressions (RegEx) used in the code above. Here is what they mean in the order they are encountered in code:
"\\s{0,};\\s{0,}"
Used with the String#split() method for parsing a semicolon (;) delimited line. This regex pretty much covers the bases for when semicolon delimited string data needs to be split but the semicolon may be spaced in several different fashions within the string, for example:
"data;data ;data; data ; data; data ;data"
\\s{0,} 0 or more whitespaces before the semicolon.
; The literal semicolon delimiter itself.
\\s{0,} 0 or more whitespaces after the semicolon.
"\\s+"
Used with the String#split() method for parsing a whitespace (" ") delimited line. This regex pretty much covers the bases for when whitespaced delimited string data needs to be split but there may be anywhere from 1 to several whitespace or tab characters separating the string tokens for example:
"datadata" Split to: [datadata] (Need at least 1 space)
"data data" Split to: [data, data]
"data data" Split to: [data, data]
"data data data" Split to: [data, data, data]
"-?\\d+|\\+?\\d+"
Used with the String#matches() method for string numerics validation. This regex is used to see if the tested string is indeed a string representation of a signed or unsigned integer numerical value (of any length). Used in the code above for numerical string validation before converting that numerical value to Integer. String representations can be:
-1 1 324 +2 342345 -65379 74 etc.
-? If the string optionally starts with or doesn't start with the
Hyphen character indicating a signed value.
\\d+ The string contains 1 or more (+) digits from 0
to 9.
| Logical OR
\\+? If the string optionally starts with or doesn't start with the
Plus character.
\\d+ The string contains 1 or more (+) digits from 0
to 9.
"\\s{0,},\\s{0,}|\\s+" (must be in this order)
Used with the String#split() method for parsing a comma (,) delimited line. This regex pretty much covers the bases for when comma delimited string data needs to be split but the comma may be spaced in several different fashions within the string, for example:
"my data,data" Split to: [my, data, data]
"my data ,data" Split to: [my, data, data]
"my data, data" Split to: [my, data, data]
"my data , data" Split to: [my, data, data]
"my data, data" Split to: [my, data, data]
"my data ,data" Split to: [my, data, data]
\\s{0,} 0 or more whitespaces before the comma.
, The literal comma delimiter itself.
\\s{0,} 0 or more whitespaces after the comma.
| Logical OR split on...
\\s+ Just one or more whitespace delimiter.
So in other words, split on either: just comma OR split on comma and one or more whitespaces OR split on one or more whitespaces and comma OR split on one or more whitespaces and comma and one or more whitespaces OR split on just one or more whitespaces
"-?\\d+(\\.\\d+)?"
Used with the String#matches() method for string numerics validation. This regex is used to see if the tested string is indeed a string representation of a signed or unsigned integer or double type numerical value (of any length). Used in the code above for numerical string validation before converting that numerical value to Double. String representations can be:
-1.34 1.34 324 2.54335 342345 -65379.7 74 etc.
-? If the string optionally starts with or doesn't start with the
Hyphen character indicating a signed value.
\\d+ The string contains 1 or more (+) digits from 0
to 9. [The string would be considered Integer up to this point.]
( Start of a Group.
\\. If the string contains a literal Period (.) after the first set of digits.
\\d+ The string contains 1 or more (+) digits from 0 to 9 after the Period.
) End of Group.
? The data expressed within the Group expression may or may not be there making the Group an Option Group.
Hopefully, the above should be able to get you started.
A regex would probably be a better choice instead of a nextInt or a nextDouble. You could fetch each decimal value using
Pattern p = Pattern.compile("\\d+(\\.\\d+)?");
Matcher m = p.matcher(a);
while(m.find()) {
System.out.println(m.group());
}
The regex checks for all occurrences of a decimal or non-decimal number in the given string.
\\d+ - One or more occurrence of a digit
(\\.\\d+) - Followed by a decimal and one or more digits
? - The expression in the parantheses is optional. So, the numbers may or may not contain decimals.
This will print the below for the data you provided
25
25
3.2
1
3.2
1
EDIT:
The problem you have with commas and semi-colons while parsing the line can be avoided by fetching the entire line using nextLine() instead of next(). next() only fetches one token at a time from the input. Using nextLine and a regular expression, you can read individual numbers as below.
while (sc.hasNext()) {
Pattern p = Pattern.compile("\\d+(\\.\\d+)?");
Matcher m ;
int population = -1;
double median = -1;
double scatter = -1;
String input = sc.nextLine(); // fetches the entire line
if (input.contains("pop")) {
m = p.matcher(input);
while (m.find()) {
population = Integer.parseInt(m.group());
}
} else if (input.contains("house")) {
m = p.matcher(input);
m.find();
median = Double.parseDouble(m.group());
m.find();
scatter = Double.parseDouble(m.group());
}
}
How would I do java regex for the following examples each its taken in by scanner as a string and regex can only be set after the scanner has taken in each part so where regex can be set is after the scanner e.g
Scanner scan = new Scanner(System.in);
String veriableName = scan.nextLine();
String studentID = scan.nextLine();
String word = scan.nextLine();
................
//regex can only be set here
String veriableNamePattern = "";
String studentIDPattern="";
String wordPattern="";
.............
if(veriableNamePattern.matches(veriableNamePattern ){
System.out.println(veriableName + " is valid.");
}
else{
System.out.println(studentID + " is valid.");
}
here are the examples I am trying to do:
A variable name composed of some alphabetic character followed by any sequence of letters or numbers.
A student ID number represented by 7 digits that must start with 1 and end with the letter s.
Any four letter word that ends in ‘ed’.
A product code represented by two digits followed by three capital letters.
Find all € values from €100 to €999 at the beginning of a line.
Just.. read through your code, treat it like a term paper, you proofread those too, surely:
You are calling veriableNamePattern.matches(veriableNamePattern) - it won't, of course. You want to match veriableName.
You print studentID + " is valid." in both cases, making it impossible to tell the difference. presumably you want to introduce a not somewhere in that second println lline.
Some examples:
// first letter optionally followed by a letter/number/underscore (\w) group
String variablePattern = "[a-zA-Z]\\w*";
// Sequence of digits starting with 1, followed by 6 digits, ending with 's' or 'S'
String studentIdPattern = "1[0-9]{6,6}s|S";
// Sequence of 2 letters followed by "ed"
String fourEdPattern = "[a-zA-Z]{2,2}ed";
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