2

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.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Abhishek
  • 688
  • 6
  • 21

3 Answers3

3

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*$
Sweeper
  • 213,210
  • 22
  • 193
  • 313
1

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}.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • @Abhishek I have just noticed you wanted to match a string that has no whitespace. I updated the answer to account for that. The previous variant that allows any chars in the string is in the [answer history](https://stackoverflow.com/revisions/59355448/1). – Wiktor Stribiżew Dec 17 '19 at 08:40
0

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.

asynts
  • 2,213
  • 2
  • 21
  • 35