1

Problem

I am trying to achieve a regular expression which matches [0-9]:[0-9] or [0-9].[0-9] or [0-9] or [0-9]: or [0-9].

What I have tried

/^\d?(\d+)?((\.|\:|\d)$|(\.|\:|\d)(\d+)?\d$)/ 

This regex which is satisfying my condition.

My optimized code

\d+[\.:]*\d* 

But this is accepting 2:2:. Actually it should not. Not able to solve this.

2
  • Try ^\d+(?:[.:]\d*)?$, see demo. Commented Feb 4, 2019 at 14:16
  • normally regexps compile into an optimised form (A finite automaton), so why to try to optimise them yourself? The expression you got in the first case worked, then use it. There's no more efficiency in the second, it's simpler because it matches a simpler form of input. As both parse input in one pass, executing the same automaton algorithm (from state X with input Y, goto state Z and accept or not) the only thing that changes is the table used for parsing. Commented Feb 5, 2019 at 18:17

3 Answers 3

1

Your \d+[\.:]*\d* is not anchored and matches partial substrings matching the pattern. Also, it matches 11.....::::: like strings as [.:]* matches 0+ . or : chars.

You may use

^\d+(?:[.:]\d*)?$ 

See the regex demo.

Details

  • ^ - start of string
  • \d+ - 1+ digits
  • (?: - start of a non-capturing group matching
    • [.:] - one . or :
    • \d* - 0+ digits
  • )? - 1 or 0 times
  • $ - end of string.
Sign up to request clarification or add additional context in comments.

1 Comment

@RinoRaj Hi, can I ask for a favor? I think this question was incorrectly marked as dupe. Could you please cast a reopen vote? (Please do not reply to the comment, I will remove it soon.)
1

How about \d([:.]\d?)?? That should handle all the cases you mentioned.

Or \d+([:.]\d*?)? if you want to accept more than one digit in each number.

To only match if exact simply add ^ to the start and $ to the end of the regular expression. Example:

const regex = /^\d+([:.]\d*?)?$/ console.log(regex.test('2')) console.log(regex.test('2:')) console.log(regex.test('2.')) console.log(regex.test('2:3')) console.log(regex.test('2.3')) console.log(regex.test('12:23')) console.log(regex.test('23.34')) console.log(regex.test('2:3:4')) console.log(regex.test('2.3.4'))

4 Comments

no problem :). You dont need the least quantifier anyway, or do you?
@JamesCoyle I tried (/\d+([:.]\d*?)?/).test('2:2:'). I am getting the result as true. Actually it should fail.
That's because it has found it twice. Regex.test will return true if any part of the string matches. I've edited with a solution.
Now, it is next to identical to my solution, while the \d*? lazy digit matching pattern makes it less efficient than with a greedy quantifier.
0

2:2: is not getting matched completely, only the substring 2:2

To avoid this, just use the anchors ^ and $ like you used in the original pattern. Following is a working regex sample using your optimized regex with the anchors added - /^\d+[.:]?\d*$/, and here's a link to it https://regexr.com/47msc

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.