Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex to match nothing but zeroes after the first zero

Tags:

regex

Using regular expressions, how can I make sure there are nothing but zeroes after the first zero?

ABC1000000 - valid 3212130000 - valid 0000000000 - valid ABC1000100 - invalid 0001000000 - invalid 

The regex without validation would be something like this - [A-Z0-9]{10}, making sure it is 10 characters.

like image 314
Sam Avatar asked Nov 01 '21 14:11

Sam


People also ask

What does regex 0 * 1 * 0 * 1 * Mean?

Basically (0+1)* mathes any sequence of ones and zeroes. So, in your example (0+1)*1(0+1)* should match any sequence that has 1. It would not match 000 , but it would match 010 , 1 , 111 etc. (0+1) means 0 OR 1.

Does empty regex match everything?

An empty regular expression matches everything.

What does \+ mean in regex?

Example: "a\+" matches "a+" and not a series of one or "a"s. ^ the caret is the anchor for the start of the string, or the negation symbol. Example: "^a" matches "a" at the start of the string. Example: "[^0-9]" matches any non digit. $ the dollar sign is the anchor for the end of the string.

How do you match a blank line in regex?

The most portable regex would be ^[ \t\n]*$ to match an empty string (note that you would need to replace \t and \n with tab and newline accordingly) and [^ \n\t] to match a non-whitespace string.


2 Answers

You could update the pattern to:

^(?=[A-Z0-9]{10}$)[A-Z1-9]*0+$ 

The pattern matches:

  • ^ Start of string
  • (?=[A-Z0-9]{10}$) Positive looakhead, assert 10 allowed chars
  • [A-Z1-9]* Optionally match any char of [A-Z1-9]
  • 0+ Match 1+ zeroes
  • $ End of string

Regex demo

If a value without zeroes is also allowed, the last quantifier can be * matching 0 or more times (and a bit shorter version by the comment of @Deduplicator using a negated character class):

^(?=[A-Z0-9]{10}$)[^0]*0*$ 

An example with JavaScript:

const regex = /^(?=[A-Z0-9]{10}$)[^0]*0*$/; ["ABC1000000", "3212130000", "0000000000", "ABC1000100", "0001000000"] .forEach(s =>   console.log(`${s} --> ${regex.test(s)}`) );

As an alternative without lookarounds, you could also match what you don't want, and capture in group 1 what you want to keep.

To make sure there are nothing but zeroes after the first zero, you could stop the match as soon as you match 0 followed by 1 char of the same range without the 0.

In the alternation, the second part can then capture 10 chars of range A-Z0-9.

^(?:[A-Z1-9]*0+[A-Z1-9]|([A-Z0-9]{10})$) 

The pattern matches:

  • ^ Start of string
  • (?: Non capture group for the alternation |
    • [A-Z1-9]*0+[A-Z1-9] Match what should not occur, in this case a zero followed by a char from the range without a zero
    • | Or
    • ([A-Z0-9]{10}) Capture group 1, match 10 chars in range [A-Z0-9]
  • $ End of string
  • ) Close non capture group

Regex demo

like image 131
The fourth bird Avatar answered Oct 24 '22 17:10

The fourth bird


0[^0]

  • a 0 followed by NOT a 0

I've written it in JS because it was easier to test, but it works in other languages as well. Note: it does not check length, but this regex is so much easier, combine this with a length check and your done.

If the regex matches, the string is invalid :) In the console I've negated it already to tell you if it is valid:

const strings = [   'BC1000000',   '3212130000',   '0000000000',   'ABC1000100',   '0001000000',   '1000000000',   '10000000000',   '1000000001' ];  strings.forEach(element => {     console.log(         element,         // true means length 10 and only trailing zeros          !/0[^0]/.test(element) && element.length == 10       ) });
like image 29
Martijn Avatar answered Oct 24 '22 19:10

Martijn