yqlim
yqlim

Reputation: 7080

Javascript same regular expression return different result

I have a code as below:

var regexp = /((^\u002b[6][0]([1-9]{2}))|(^[0]([1-9]{1})))((\s)|(\u002d)|(\s\u002d\s)?)(\d{3,})((\s)|(\u002d)|(\s\u002d\s)?)(\d{3})(\d)?$/,
    str = '+60123456789',
    boo = 'false';

(!regexp.test(str)) ? boo = 'false' : boo = 'true';

console.log(boo);

I tested the code and the result returned boo = 'true' on this jsFiddle but boo = 'false' on my localhost.

Why is that? Is there anything wrong with my regexp code?

EDIT :

Thanks @Cerbrus and @smnbbrv for pointing out my weird ternary statement.

I corrected it but still getting different result in jsFiddle and my localhost.

var regexp = /((^\u002b[6][0]([1-9]{2}))|(^[0]([1-9]{1})))((\s)|(\u002d)|(\s\u002d\s)?)(\d{3,})((\s)|(\u002d)|(\s\u002d\s)?)(\d{3})(\d)?$/,
    str = '+60123456789',
    boo = 'false';

boo = regexp.test(str) ? 'true' : 'false';

console.log(boo);

EDIT 2:

I made a mistake at the previous jsFiddle. Corrected it here but still getting discrepancy.

As requested by @Wiktor Stribiżew, my regexp is to filter numbers. It should accept any number starting with either +60 follow by any two number or 0 follow by any one number. The middle part is just to allow whitespaces and hyphens.

Apparently I also caused a minor fight between @Jaromanda X and @Newbee Dev (who I appreciate a lot for helping!). My str value is identical after checking. And localhost is indeed still showing different result.

EDIT 3 :

To @Joe : I ran my localhost using Microsoft WebMatrix 3, for that matters. And both instances are using the same browser.

EDIT 4 :

Thanks @Joe for his detailed examination of my regex here. However, the discrepancy on my end still persists.

Updated the regexp according to his advice.

regexp = /((^\u002b[6][0]([1-9]{2}))|(^[0]([1-9]{1})))((\s)|(\u002d)|(\s\u002d\s)?)(\d{3,4})((\s)|(\u002d)|(\s\u002d\s)?)(\d{3})(\d)?$/;
                                                                                         ^

New jsFiddle here.

Upvotes: 2

Views: 208

Answers (1)

Joe
Joe

Reputation: 28326

You regex has a slight ambiguity.

/((^\u002b[6][0]([1-9]{2}))|(^[0]([1-9]{1})))((\s)|(\u002d)|(\s\u002d\s)?)(\d{3,})((\s)|(\u002d)|(\s\u002d\s)?)(\d{3})(\d)?$/

If we break this down one part at a time:

((^\u002b[6][0]([1-9]{2}))|(^[0]([1-9]{1})))
will match +60 followed by 2 non-zero digits, or 0 followed by 1 non-zero digit

((\s)|(\u002d)|(\s\u002d\s)?)
will match a single space, a single dash or a dash surrounded by spaces, or nothing.

(\d{3,})
then matches 3 or more digits <- This is where the ambiguity lies. Depending on how greedy the regex matcher is, this may consume to the end of the string if there are only digits left.

((\s)|(\u002d)|(\s\u002d\s)?)
repeat of before

(\d{3})
matches exactly 3 digits <- if the previous pattern greedily matched to the end of the string, this pattern will not match as all of the digits were consumed.

(\d)?
one digit or no digits

tl;dr
This regular expression is completely valid, but will give different results depending on the greediness setting of the engine that applies it.

Upvotes: 2

Related Questions