Skip to content
Advertisement

Dynamic Regex for Decimal Precision not Working

I have the following hard-coded RegEx expression for decimal precision & scale, which works (in another project):

// This would be a Decimal(2,3)
var regex = /d{0,2}(.d{1,3})?$/;
var result = regex.test(text);

However, I don’t want to hard-code multiple variations. And, interestingly, the following fails…but I don’t know why.

I “think” the concatenation may (somehow) be effecting the “test”

  • What am I doing wrong here?

SAMPLE:

var validationRules = {
    decimal: {
        hasPrecision: function (precision, scale, text) {

            var regex = new RegExp('d{0,' + precision + '}(.d{1,' + scale + '})?$'); 
            var result = regex.test(text);

            // result is ALWAYS true ????
            alert(result);
            alert(regex);
        }
    }
};

FAILING SAMPLE-SNIPPET:

$(document).ready(function () {

            var validationRules = {
                decimal: {
                    hasPrecision: function (precision, scale, text) {
                        
                        var regex = new RegExp('d{0,' + precision + '}(.d{1,' + scale + '})?$'); 
                        var result = regex.test(text);

                        alert(result);
                        alert(regex);
                    }
                }
            };

            var masks = {
                decimal: function (e) {

                    // TODO: get Kendo MaskedTextBox to run RegEx
                    var regex = new RegExp("^([0-9.])$");
                    var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);

                    if (!regex.test(key)) {
                        event.preventDefault();
                        return false;
                    }
                }
            };

            var button = $('.btn');
            var textbox = $('.txt');

            textbox.on('keypress', masks.decimal);
            button.on('click', function () {
                var text = textbox.val();

                validationRules.decimal.hasPrecision(2, 3, text);
            });
        });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="1111" class="txt">
<input type="button" class="btn" value="Run it">

Advertisement

Answer

Always look at the result when building dynamic strings. In your case you’re building it and just assuming it’s turning into the REGEX pattern you want.

What you’re actually building is, for example:

d{0,2}(.d{1,3})?$

Why? Because REGEX patterns built via the constructor (as opposed to literals) are built as strings – and in strings is interpreted as an escape character.

You, however, need these back slashes to persist into your pattern, so you need to double escape. In effect, you need to escape the escape so the final one is retained.

var regex = new RegExp('\d{0,' + precision + '}(\.\d{1,' + scale + '})?$');

This will result in an equivalent of your hard-coded pattern assuming precision and scale contain the intergers you think they do. Check this too. (If they contain floats, for example, this will ruin your pattern.)

As for your false positives, this is probably down to a missing start-anchor instruction, i.e. ^.

/d{0,2}(.d{1,3})?$/.test("1234"); //true
/^d{0,2}(.d{1,3})?$/.test("1234"); //false, note ^
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement