migu
migu

Reputation: 4336

Ruby flavoured Regex: A[[:digit:]]* accepts character at the beginning of string

I have the following Ruby flavoured regex:

data.to_s.match(/\A[[:digit:]]*+((.|,)[[:digit:]]+)?\Z/) ? true : false

This returns true for the following examples as intended:

data = "13"
data = "1,3"
data = "13,3"
data = "1.3"
data = ",3"
data = ".3"

What is not clear to me is why the asterix after the first [[:digit:]] also allows a character to be passed at the beginning of the string:

irb > "a3".match(/\A[[:digit:]]*+((.|,)[[:digit:]]+)?\Z/)
=> #<MatchData "a3" 1:"a3" 2:"a">

How can I have it only match digits?

Upvotes: 1

Views: 90

Answers (2)

dbenhur
dbenhur

Reputation: 20408

. is a regexp metachar that matches any character (except newline) you need to escape it in your alternation:

data.to_s.match(/\A[[:digit:]]*((\.|,)[[:digit:]]+)?\Z/) ? true : false
# this dot needs escaping         ^

Also the + after the first * is redundant (one or more repetitions of zero or more digits). Also ruby has a shorter friendly way to say [[:digit:]]: \d. Since this is a whole string match, do you really want to allow \n at end of string? If not, use \z over \Z

data.to_s.match(/\A\d*((\.|,)\d+)?\z/) ? true : false

Upvotes: 3

Ben Lee
Ben Lee

Reputation: 53319

The . in your regex is matching any character and needs to be escaped as \.:

data.to_s.match(/\A[[:digit:]]*+((\.|,)[[:digit:]]+)?\Z/) ? true : false

Upvotes: 1

Related Questions