Matcher result - regex

Viewed 113
final String regex = "^[A-Za-z0-9]{1,12}$";
final Pattern pattern = Pattern.compile(regex);

System.out.println(pattern.matcher("hi!").?);

Is there a way to get what went wrong with Matcher? In this case, "!" is not allowed, as you can see from regex. I'd like to have a result, something like "'!' is not allowed".

3 Answers

You can replace all characters as per the pattern with "" which will give you the characters that are not allowed. However, there is a catch here: the pattern that I have used does not have a start-of-line (^) and end-of-line ($) which is something I will think about and update.

Demo:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        final String regex = "[A-Za-z0-9]{1,12}";

        String str = "hi!&";

        String remaining = str.replaceAll(regex, "");

        System.out.println("The following characters are not allowed: " + Arrays.toString(remaining.split("")));
    }
}

Output:

The following characters are not allowed: [!, &]

You can test first if the regex matches (with the matches() function there is no reason to add ^ and $), then if there is no match you can handle some possible cases:

public void complianceCheck(String inputString) {
    final String regex = "[A-Za-z0-9]{1,12}";
    
    if (!Pattern.compile(regex).matcher(inputString).matches()) {
        Matcher matcher = Pattern.compile(regex).matcher(inputString);
        if (matcher.find()) {
            String match = matcher.group(0);
            if (Pattern.compile("^" + regex).matcher(inputString).find())
                System.out.printf("'%s' shouldn't be followed by '%s'\n", match, inputString.replaceFirst("^" + regex, ""));
            else if (Pattern.compile(regex + "$").matcher(inputString).find())
                System.out.printf("'%s' shouldn't be preceded by '%s'\n", match, inputString.replaceFirst(regex + "$", ""));
            else
                System.out.printf("%s shouldn't be between something else\n", match);
        }
        else System.out.println("No match");
    }
    else System.out.println("OK");
}

@Test
public void test() {
    complianceCheck("hi!");    // this will print "'hi' shouldn't be followed by '!'"
    complianceCheck("...hi");  // this will print "'hi' shouldn't be preceded by '...'"
    complianceCheck("...hi!"); // this will print "'hi' shouldn't be between something else"
    complianceCheck("...");    // this will print "No match"
    complianceCheck("hi");     // this will print "OK"
}

Your regular expression is matching any string composed of a limited set of characters, with a maximum length.

You can easily check length by other means. For unmatched characters, just test the opposite.

public static void main (String[] args) throws java.lang.Exception
{
    System.out.println(test("hello !"));
    System.out.println(test("hello"));
}

public static boolean test(String input) {
  if (input.length() < 1) {
    System.err.println("Too short");
    return false;
  }
  if (input.length() > 12) {
    System.err.println("Too long");
    return false;
  }
  final Pattern pattern = Pattern.compile("[^A-Za-z0-9]");
  Matcher m = pattern.matcher(input);
  boolean rejected = false;
  while (m.find()) {
    System.err.println(m.group(0) + " not allowed!");
    rejected = true;
  }
  return !rejected;
}
Related