8

I'm trying to create a regular expression in javascript for a UK bank sort code so that the user can input 6 digits, or 6 digits with a hyphen between pairs. For example "123456" or "12-34-56". Also not all of the digits can be 0. So far I've got /(?!0{2}(-?0{2}){2})(\d{2}(-\d{2}){2})|(\d{6})/ and this jsFiddle to test.

This is my first regular expression so I'm not sure I'm doing it right. The test for 6 0-digits should fail and I thought the -? optional hyphen in the lookahead would cause it to treat it the same as 6 0-digits with hyphens, but it isn't. I'd appreciate some help and any criticism if I'm doing it completely incorrectly!

NickL
  • 1,870
  • 2
  • 15
  • 35

2 Answers2

12

Just to answer your question, you can validate user input with:

/^(?!(?:0{6}|00-00-00))(?:\d{6}|\d\d-\d\d-\d\d)$/.test(inputString)

It will strictly match only input in the form XX-XX-XX or XXXXXX where X are digits, and will exclude 00-00-00, 000000 along with any other cases (e.g. XX-XXXX or XXXX-XX).

However, in my opinion, as stated in other comments, I think it is still better if you force user to either always enter the hyphen, or none at all. Being extra strict when dealing with anything related to money saves (unknown) troubles later.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
  • @ScottS: If there is something wrong, just comment if the post is new. I'm right here to edit it. – nhahtdh Jul 05 '12 at 10:26
  • I think according to this http://jsfiddle.net/sd88a/2/ it's not working for 6 non-0 digits with hyphens – NickL Jul 05 '12 at 10:29
  • 1
    @nhahtdh Ok, I just fixed the regex, adding the `{2}` to the `(\d{6}|(\d{2}-)\d{2})` to make it `(\d{6}|(\d{2}-){2}\d{2})`. @NickL this is the issue you are experiencing. – Scott Stevens Jul 05 '12 at 10:30
  • Cheers for that guys, and I agree with only allowing numbers but unfortunately dealing with some legacy applications, so have to be prepared – NickL Jul 05 '12 at 10:34
  • @NickL Edited my post to complete the use case. – nhahtdh Jul 05 '12 at 10:35
  • Gravedigging a little here - this will match "௫௬-௭௮-௯౦" as a valid sort code (which it isn't) - should use [0-9] instead of \d in order to only match numeric digits relevant to the culture. – PhonicUK May 23 '13 at 14:28
  • @PhonicUK: Nope. This is JavaScript. `\d` is effectively equivalent to `[0-9]` in JS. – nhahtdh May 23 '13 at 14:30
4

Since any of the digits can be zero, but not all at once, you should treat the one case where they are all zero as a single, special case.

You are checking for two digits (\d{2}), then an optional hyphen (-?), then another two digits (\d{2}) and another optional hyphen (-?), before another two digits (\d{2}).

Putting this together gives \d{2}-?\d{2}-?\d{2}, but you can simplify this further:

(\d{2}-?){2}\d{2}

You then use the following pseudocode to match the format but not 000000 or 00-00-00:

if (string.match("/(\d{2}-?){2}\d{2}/") && !string.match("/(00-?){2}00/"))
     //then it's a valid code, you could also use (0{2}-?){2}0{2} to check zeros

You may wish to add the string anchors ^ (start) and $ (end) to check the entire string.

Scott Stevens
  • 2,546
  • 1
  • 20
  • 29
  • 2
    Your regex will match `45-5454`, not sure if this is allowed, since OP says that either no hyphen, or hyphen between pairs. – nhahtdh Jul 05 '12 at 10:14
  • @nhahtdh But accepting that's less harmful than the contortions required to get everything into a single perfect RE. Better to normalize after acceptance by removing hyphens (at which point, `45-4545` won't matter). – Donal Fellows Jul 05 '12 at 10:16
  • @DonalFellows: It is possible to get everything into single regex, with what Javascript supports (negative look-ahead). I think online banking are doing right by enforcing a single way to enter the credit card numbers - no need for input normalization, only strict checking. The user won't be able to complain anything, since there is only one way to input. – nhahtdh Jul 05 '12 at 10:24