简体   繁体   中英

Slow regex query when the string contains special chars

I have a regex as follows /^(\\s*\\(*\\s*[0-9]*\\s*[+\\-*/]?\\s*[0-9]*\\s*\\)*\\s*)*$/ it's not perfect, but it's designed as a fast check that the string being input is a basic math formula, eg, 7 * 9 * (6 + 5) . I do secondary checks if this passes to look for unclosed parenthesis (the formula is also allowed to end on an operator).

Javascript's String.prototype.match is able to use the regex to very quickly match against some strings, eg, "7 * 912 + 6 + 7 +".match(regex) - but is very slow against others:

  1. "7 * 912 + 6 + $ +".match(regex)
  2. "7 * 912 + 6 + ^ +".match(regex)
  3. "7 * 912 + 6 + [ +".match(regex)
  4. "7 * 912 + 6 + ] +".match(regex)

It is however fast for: "7 * 912 + $ +".match(regex)

Presumably the reason for this is that the string contains special chars, combined with the ? in the middle (the problem goes away if I remove that) - but only when a certain number of operators are combined? Is there a way to improve the performance of this? Right now I'm just pre-checking for any special chars (since none are allowed anyway) but I'd like something cleaner.

Detecting a well-formed expression is pretty complicated - I would not attempt the whole thing using a single regex - I'd expand your multiple pass approach to the level required to meet your needs. I would definitely start with a basic character filter:

var charRegex = /[^0-9+\-*\(\)\s]/i;
function testString(str) {
    if (!charRegex.test(str)) {
        // fail
        return false;
    }
    // do further tests...
}

Your further testing could include regex's to test for multiple operators in a row, unclosed brackets, etc. And if you do this inside a function, you can early return at the first failed test.

To really do this fully, I think you need some sort of recursive function, not a series of tests on the whole string. But if you don't want to go that far, I think a series of simpler regex's may be good enough for your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM