I want to create a regex in Java to match at least 1 alphabet and 1 non-alphabet (could be anything except A-Za-z) and no white space.
Below Regex is working partially correct:
^([A-Za-z]{1,}[^A-Za-z]{1,})+$
It matches aaaa7777
but doesn't match 777aaaaa.
Any Help would be appreciated.
Your regex implicitly assumes the order of the characters you want to match. The regex is saying that a letter must come before a non-latter. However, you want the letter and the non-letter to come in either order, so you need to account for both cases. Also note that it should be [^\sa-zA-Z] instead of [^a-zA-Z] as you don't allow spaces.
(?:[a-zA-Z][^\sa-zA-Z]|[^\sa-zA-Z][a-zA-Z])
At the start and end, any non-space character is allowed, so:
^\S*(?:[a-zA-Z][^\sa-zA-Z]|[^\sa-zA-Z][a-zA-Z])\S*$
You may use
s.matches("(?=\\P{Alpha}*\\p{Alpha})(?=\\p{Alpha}*\\P{Alpha})\\S*")
This is how the pattern works.
Details
The pattern will match a whole string since ^ and \z anchors are implicit in matches
(?=\P{Alpha}*\p{Alpha}) - a lookahead that requires at least one ASCII letter after any 0+ chars other than an ASCII letter
(?=\p{Alpha}*\P{Alpha}) - a lookahead that requires a char other than an ASCII letter after 0 or more ASCII letters
\S* - zero or more non-whitespace chars.
To make the regex Unicode aware replace \p{Alpha} with \p{L} and \P{Alpha} with \P{L}.
Regular expressions aren't the right tool for this type of validation. Just write out the plain logic, your specific example:
public class Main {
public static void main(String[] args) {
System.out.println("'foo' ? " + doesMatch("foo"));
System.out.println("'bar7' ? " + doesMatch("bar7"));
System.out.println("'55baz' ? " + doesMatch("55baz"));
}
public static boolean doesMatch(String input) {
boolean hasAlpha = false,
hasNonAlpha = false;
for(char ch : input.toCharArray()) {
if(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
hasAlpha = true;
} else {
hasNonAlpha = true;
}
if(hasAlpha && hasNonAlpha) {
return true;
}
}
return false;
}
}
Anyone can understand what inputs do match and which inputs don't. If you use regular expressions this wouldn't be so simple.
Related
I want to validate a string in java. It should not allow any special characters, example #._ at dot underscore. Only these 3 characters should be allowed. No space is allowed. And only English alphabets allowed.
You can use regex (Regular Expressions):
public static boolean isValid(String s)
{
return s.matches("[a-zA-Z#._]*");
}
Explanation:
[a-zA-Z#._]: Matches a single character that is either in the English
alphabet, or the three special characters '#', '.' and '_'.
*: Matches the previous expression between zero and unlimited times.
Note: If empty strings are not valid either, use [a-zA-Z#._]+ as the regex
instead, or additionally test whether s.isEmpty() or has length of 0.
I'll assume you're reading user input with a Scanner object, and can use the Character wrapper class methods. This is pretty much as easy to understand as it gets:
Scanner stdin = new Scanner(System.in);
String userInput = stdin.nextLine();
boolean valid = true;
for(int i = 0; i < userInput.length; i++){
if(!Character.isDigit(ch) && !Character.isLetter(ch) && ch != '#' && ch !='_' && ch != '.'){
valid = false;
break;
}
}
// Code that deals with result.
i want to have regular expression to check input character as a-z and 0-9 but i do not want to allow input as just numeric value at all ( must be have at least one alphabetic character)
for example :
413123123123131
not allowed but if have just only one alphabetic character in any place of phrase it's ok
i trying to define correct Regex for that and at final i raised to
[0-9]*[a-z].*
but in now i confused how to defined {x,y} length of phrase i want to have {9,31} but after last * i can not to have length block too i trying to define group but unlucky and not worked
tested at https://www.debuggex.com/
how can i to add it ??
What you seek is
String regex = "(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*";
Use it with String#matches() / Pattern#matches() method to require a full string match:
if (s.matches(regex)) {
return true;
}
Details
^ - implicit in matches() - matches the start of string
(?=.{9,31}$) - a positive lookahead that requires 9 to 31 any chars other than line break chars from the start to end of the string
\\p{Alnum}* - 0 or more alphanumeric chars
\\p{Alpha} - an ASCII letter
\\p{Alnum}* - 0 or more alphanumeric chars
Java demo:
String lines[] = {"413123123123131", "4131231231231a"};
Pattern p = Pattern.compile("(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*");
for(String line : lines)
{
Matcher m = p.matcher(line);
if(m.matches()) {
System.out.println(line + ": MATCH");
} else {
System.out.println(line + ": NO MATCH");
}
}
Output:
413123123123131: NO MATCH
4131231231231a: MATCH
This might be what you are looking for.
[0-9a-zA-Z]*[a-zA-Z][0-9a-zA-Z]*
To help explain it, think of the middle term as your one required character and the outer terms as any number of alpha numeric characters.
Edit: to restrict the length of the string as a whole you may have to check that manually after matching. ie.
if (str.length > 9 && str.length < 31)
Wiktor does provide a solution that involves more regex, please look at his for a better regex pattern
Try this Regex:
^(?:(?=[a-z])[a-z0-9]{9,31}|(?=\d.*[a-z])[a-z0-9]{9,31})$
OR a bit shorter form:
^(?:(?=[a-z])|(?=\d.*[a-z]))[a-z0-9]{9,31}$
Demo
Explanation(for the 1st regex):
^ - position before the start of the string
(?=[a-z])[a-z0-9]{9,31} means If the string starts with a letter, then match Letters and digits. minimum 9 and maximum 31
| - OR
(?=\d.*[a-z])[a-z0-9]{9,31} means If the string starts with a digit followed by a letter somewhere in the string, then match letters and digits. Minimum 9 and Maximum 31. This also ensures that If the string starts with a digit and if there is no letter anywhere in the string, there won't be any match
$ - position after the last literal of the string
OUTPUT:
413123123123131 NO MATCH(no alphabets)
kjkhsjkf989089054835werewrew65 MATCH
kdfgfd4374985794379857984379857weorjijuiower NO MATCH(length more than 31)
9087erkjfg9080980984590p465467 MATCH
4131231231231a MATCH
kjdfg34 NO MATCH(Length less than 9)
Here's the regex:
[a-zA-Z\d]*[a-zA-Z][a-zA-Z\d]*
The trick here is to have something that is not optional. The leading and trailing [a-zA-Z\d] has a * quantifier, so they are optional. But the [a-zA-Z] in the middle there is not optional. The string must have a character that matches [a-zA-Z] in order to be matched.
However, you need to check the length of the string with length afterwards and not with regex. I can't think of any way how you can do this in regex.
Actually, I think you can do this regexless pretty easily:
private static boolean matches(String input) {
for (int i = 0 ; i < input.length() ; i++) {
if (Character.isLetter(input.charAt(i))) {
return input.length() >= 9 && input.length() <= 31;
}
}
return false;
}
I need to check a palindrome in a separate class but ignore non alphabet characters. So for example, radar would still qualify if it was written r,a,d,a,r
I believe I could use regex, but I don't know how.
Here is what I have so far,
public static boolean isNonAlpha(char c) {
return (c == '-' || c == '.' || c == ' ' || c == ')' || c == '(') || c == '<' || c == '>' || c == ',';
}
public static String checkInput(String test){
int startChar = 0;
int endChar = test.length() - 1;
while (startChar < endChar) {
if (test.charAt(startChar) != test.charAt(endChar)) {
System.out.println("Your word is not a palindrome.");
System.exit(0);
} else {
if (test.charAt(startChar) == test.charAt(endChar))
startChar++;
endChar--;
}
}
System.out.println("Your word is indeed a palindrome.");
return test;
}
I'm stuck on how to incorporate my isNonAlpha method, or how to use regex
You can use this pattern with the matches method (add the case insensitive option if you want):
(?:[^a-z]*([a-z])(?=.*(\1[^a-z]*\2?+)$))+[^a-z]*[a-z]?[^a-z]*\2
If you want to match a single letter too, add |[^a-z]*[a-z][^a-z]* at the end.
demo regexplanet (Java)
demo regex101
details:
The idea is to capture one by one each letters from the start of the string in group 1 and to check each time in a lookahead if the same letter is present at the end. The capture group 2 is in the lookahead and capture at the end of the string its own content (from the previous repetition) and the new letter. At each repetition the capture group 2 grows with the new letter (and other characters that are not letters).
(?: # repeated non capturing group
[^a-z]* # eventual other character before a letter
([a-z]) # the letter is captured in group 1
(?= # lookahead (to check the end of the string)
.*
(
\1 # backreference capture group1: the letter at the beginning
[^a-z]* # other characters
\2?+ # backreference capture group2: optional but possessive
# (that acts like a kind of conditional: if the group 2 already
# exists, it matches, otherwise not)
)
$ # anchor for the end of the string
)
)+
[^a-z]*[a-z]?[^a-z]* # an eventual letter in the middle
\2 # backreference capture group 2
(With the matches method, anchors are implicit.)
I have the following method which is used to insert parentheses and asterisks into a boolean expression when dealing with multiplication. For instance, an input of A+B+AB will give A+B+(A*B).
However, I also need to take into account the primes (apostrophes). The following are some examples of input/output:
A'B'+CD should give (A'*B')+(C*D)
A'B'C'D' should give (A'*B'*C'*D')
(A+B)'+(C'D') should give (A+B)'+(C'*D')
I have tried the following code but seems to have errors. Any thoughts?
public static String modify(String expression)
{
String temp = expression;
StringBuilder validated = new StringBuilder();
boolean inBrackets=false;
for(int idx=0; idx<temp.length()-1; idx++)
{
//no prime
if((Character.isLetter(temp.charAt(idx))) && (Character.isLetter(temp.charAt(idx+1))))
{
if(!inBrackets)
{
inBrackets = true;
validated.append("(");
}
validated.append(temp.substring(idx,idx+1));
validated.append("*");
}
//first prime
else if((Character.isLetter(temp.charAt(idx))) && (temp.charAt(idx+1)=='\'') && (Character.isLetter(temp.charAt(idx+2))))
{
if(!inBrackets)
{
inBrackets = true;
validated.append("(");
}
validated.append(temp.substring(idx,idx+2));
validated.append("*");
idx++;
}
//second prime
else if((Character.isLetter(temp.charAt(idx))) && (temp.charAt(idx+2)=='\'') && (Character.isLetter(temp.charAt(idx+1))))
{
if(!inBrackets)
{
inBrackets = true;
validated.append("(");
}
validated.append(temp.substring(idx,idx+1));
validated.append("*");
idx++;
}
else
{
validated.append(temp.substring(idx,idx+1));
if(inBrackets)
{
validated.append(")");
inBrackets=false;
}
}
}
validated.append(temp.substring(temp.length()-1));
if(inBrackets)
{
validated.append(")");
inBrackets=false;
}
return validated.toString();
}
Your help will greatly be appreciated. Thank you in advance! :)
I would suggest you should start with positions of + character in your string. If they differ by 1, you dont do anything. If they differ by two then there are two possiblities: AB or A'. So you check for it. If they differ by more than 2, then just check for ' symbol and put required symbol.
You can do it in 2 passes using regular expressions:
StringBuilder input = new StringBuilder("A'B'+(CDE)+A'B");
Pattern pattern1 = Pattern.compile("[A-Z]'?(?=[A-Z]'?)");
Matcher matcher1 = pattern1.matcher(input);
while (matcher1.find()) {
input.insert(matcher1.end(), '*');
matcher1.region(matcher1.end() + 1, input.length());
}
Pattern pattern2 = Pattern.compile("([A-Z]'?[*])+[A-Z]'?");
Matcher matcher2 = pattern2.matcher(input);
while (matcher2.find()) {
int start = matcher2.start();
int end = matcher2.end();
if (start==0||input.charAt(start-1) != '(') {
input.insert(start, '(');
end++;
}
if (input.length() == end || input.charAt(end) != ')') {
input.insert(end, ')');
end++;
}
matcher2.region(end, input.length());
}
It works as follows: the regex [A-Z]'? will match a letter from A-Z (all the capital letters) and it can be followed by an optional apostrophe, so it conveniently takes care of whether there is an apostrophe or not for us. The regex [A-Z]'?(?=[A-Z]'?) then means "look for a capital letter followed by an option apostrophe and then look for (but don't match against) a capital letter followed by an option apostrophe. This wil be all the places after which you want to put an asterisk. We then create a Matcher and find all the characters that match it. then we insert the asterisk. Since we modified the string, we need to update the Matcher for it to function properly.
In the second pass, we use the regex ([A-Z]'?[*])+[A-Z]'? which will look for "a capital letter followed by an option apostrophe and then an asterisk at least one time and then a capital letter followed by an option apostrophe". this is where all the groups that parentheses need to go in lie. So we create a Matcher and find the matches. we then check to see if there is already a parentese there (making sure not to go out of bounds ). If not we add a one. We again need to update the Matcher since we inserted characters. once this is over we have or final string.
for more on regex:
Pattern documentation
Regex tutorial
I recently had an interview with Google for a Software Engineering position and the question asked regarded building a pattern matcher.
So you have to build the
boolean isPattern(String givenPattern, String stringToMatch)
Function that does the following:
givenPattern is a string that contains:
a) 'a'-'z' chars
b) '*' chars which can be matched by 0 or more letters
c) '?' which just matches to a character - any letter basically
So the call could be something like
isPattern("abc", "abcd") - returns false as it does not match the pattern ('d' is extra)
isPattern("a*bc", "aksakwjahwhajahbcdbc"), which is true as we have an 'a' at the start, many characters after and then it ends with "bc"
isPattern("a?bc", "adbc") returns true as each character of the pattern matches in the given string.
During the interview, time being short, I figured one could walk through the pattern, see if a character is a letter, a * or a ? and then match the characters in the given string respectively. But that ended up being a complicated set of for-loops and we didn't manage to come to a conclusion within the given 45 minutes.
Could someone please tell me how they would solve this problem quickly and efficiently?
Many thanks!
Assuming you are allowed to use regexes, you could have written something like:
static boolean isPattern(String givenPattern, String stringToMatch) {
String regex = "^" + givenPattern.replace("*", ".*").replace("?", ".") + "$";
return Pattern.compile(regex).matcher(stringToMatch).matches();
}
"^" is the start of the string
"$" is the end of the string
. is for "any character", exactly once
.* is for "any character", 0 or more times
Note: If you want to restrict * and ? to letters only, you can use [a-zA-Z] instead of ..
boolean isPattern(String givenPattern, String stringToMatch) {
if (givenPattern.empty)
return stringToMatch.isEmpty();
char patternCh = givenPatter.charAt(0);
boolean atEnd = stringToMatch.isEmpty();
if (patternCh == '*') {
return isPattenn(givenPattern.substring(1), stringToMatch)
|| (!atEnd && isPattern(givenPattern, stringToMatch.substring(1)));
} else if (patternCh == '?') {
return !atEnd && isPattern(givenPattern.substring(1),
stringToMatch.substring(1));
}
return !atEnd && patternCh == stringToMatch.charAt(0)
&& isPattern(givenPattern.substring(1), stringToNatch.subtring(1);
}
(Recursion being easiest to understand.)