0

When validating a zip code, I'm trying to check if the zip code that can contain alphanumeric and only the characters -, | and  (space).

I'm checking

"34343-1232".matches("(?!|| |-|[0-9])"))

but this doesn't work. Is there an optimum way to do this?

kapex
  • 28,903
  • 6
  • 107
  • 121
Roe hit
  • 457
  • 1
  • 7
  • 23
  • Are you including `{` and `}` or is that just the formatting of the question? – Paolo Sep 11 '18 at 22:16
  • Why did you make a *negative* look-ahead? – Andreas Sep 11 '18 at 22:16
  • Regex matching text containing only digits, dash, and space characters: `matches("[0-9 -]*")`. The dash must be last, so it isn't part of a character range like the `0-9`. – Andreas Sep 11 '18 at 22:18
  • @UnbearableLightness It's just formatting the question. I'm not including it in the regex – Roe hit Sep 11 '18 at 22:23
  • 1
    This question has already answered here. https://stackoverflow.com/a/2577239/9698608 – Dave Zabriskie Sep 11 '18 at 22:24
  • @Andreas This works , whatever you gave, but it's not considering the pipe. Should I add pipe anywhere in the expression or is there a sequence to this? Thank you. I want to match | and - and space – Roe hit Sep 11 '18 at 22:25
  • @UnbearableLightness No, it's not a duplicate. I need pipe and a space and a - . This maybe a zip but a clear picture is what I couldn't find in other posts. I've really looked out for explanation. Great to see all your answers. I just want to understand this concept – Roe hit Sep 11 '18 at 22:26
  • 1
    @Ronald Just add the pipe, it's not special inside a character class. Of the characters you need to match, only `-` is special, which is why it needs to be last or be escaped: `matches("[0-9 |-]*")` *(dash last)* or `matches("[0-9\\-| ]*")` *(dash escaped)* – Andreas Sep 11 '18 at 22:31

3 Answers3

2

I don't know the exact zip rules in your country, but this snippet will get you started:

// define the pattern - should be defined as class field
// instead of + you could use {3,5} to match min. 3, max. 5 characters - see regular expressions manual
private static final Pattern PATTERN_ZIP = Pattern.compile("^[0-9A-Z]+[ \\-\\|]?[0-9A-Z]+$");

String zip = "1A2-3B4C5";
// Optional: let's make some text cleaning
String cleanZip = zip.toUpperCase().trim();

// Do the mat(c)h
Matcher m = PATTERN_ZIP.matcher(cleanZip);

if (m.find()) {
    System.out.println("Zip code correct");
} else {
    System.out.println("Zip code incorrect");
}
madman_xxx
  • 104
  • 8
  • Hey, thanks for the contributing answer. For your reference, it's often best to begin or end character classes with `-`when you want to end with hyphen. This both makes it clear that you're looking for a hyphen (when coming back to the regex) and avoids having to escape or double-escape. I prefer to begin classes with `-`. Anyway, +1. – Regular Jo Sep 11 '18 at 22:57
2

Allowing for simple zip codes (e.g. 12345) and enforcing that if an accepted separator (space, comma, pipe) is found it must be trailed by four digits, this regex should suffice.

[0-9]{5}(?:[-,| ][0-9]{4})?
1

You don't need negative lookahead, you can use a character class ([]) instead of the | operators, and you'd want to use ^ and $ to denote the start and end of the string. Like this:

"34343-1232".matches("^[0-9| -]+$")
  • This won't allow for spaces though. – Paolo Sep 11 '18 at 22:30
  • Yeah, the thing is now something like *34343 multiplespaces 1232* will be matched. Not sure if OP would want that to match. – Paolo Sep 11 '18 at 22:31
  • Don't need `^` and `$` when using `matches()`. – Andreas Sep 11 '18 at 22:32
  • Yes I would want to do that match. Great answer. Its really helpful – Roe hit Sep 11 '18 at 22:32
  • @Ronald The formatting on my comment was not rendered. I am not sure this is what you want, check [this regex](https://regex101.com/r/t0SHfh/1). – Paolo Sep 11 '18 at 22:32
  • Multiple spaces are allowed in the string. Is this what you are after? Same goes for the other delimiters of course. – Paolo Sep 11 '18 at 22:33
  • I just saw the rules, It never mentioned if they want multiple spaces or just one space. If I want only 1 space, what should I do to change this? – Roe hit Sep 11 '18 at 22:35
  • 1
    @Ronald Use `^\d+[0-9| -]\d+$`, see [here](https://regex101.com/r/t0SHfh/3) – Paolo Sep 11 '18 at 22:36
  • For only one space: `"34343-1232".matches("^[0-9|-]*[0-9| -]+[0-9|-]*$")` –  Sep 11 '18 at 22:37
  • @user10340091 No need to make the pattern more complicated that it needs to be. `^\d+[0-9| -]\d+$` will work fine for OP requirements. – Paolo Sep 11 '18 at 22:38
  • As he is matching zip codes, he is probably just matching digits separated by a delimiter. – Paolo Sep 11 '18 at 22:39
  • @UnbearableLightness Yours specifies that it must start and end with one or more digits, and contain at least one of `[0-9| -]`. So "1" would not match and "12" would not match. Which usually aren't valid zip codes, but I'm being pedantic to what OP says –  Sep 11 '18 at 22:41
  • Yeah, that's true :) But `^[0-9|-]*[0-9| -]+[0-9|-]*$` is wrong, it matches empty strings, `1111111111` and `----------` – Paolo Sep 11 '18 at 22:41
  • REs like this are very irresponsible. This RE would allow `-` or `---------------------------------------`. While its working from incomplete information (only one example from the question), https://stackoverflow.com/a/52285067/3917091 is more responsible. If you're invoking regex to validate the format, you should do it properly. – Regular Jo Sep 11 '18 at 22:47
  • `^[0-9|-]*[0-9| -]+[0-9|-]*$` does not match empty strings –  Sep 11 '18 at 22:49