Javascript regex to escape quotes (but not escape already escaped quotes)

后端 未结 4 1192
情歌与酒
情歌与酒 2021-01-13 19:22

I am looking for a JavaScript regex which will escape single quotes but it should not escape single quotes which are already escaped.

相关标签:
4条回答
  • 2021-01-13 19:59

    Ideally, you want every match to start exactly where the previous match ended. Otherwise it's too easy to get out of sync with the escape sequences. @outis's regex comes close, but it fails to escape the second single-quote in '\\'. After the first match, it has to match at least one non-backslash and one single-quote, which it can't do. If there are any more characters, it skips ahead and starts matching after the second single-quote.

    Try this one instead:

    result = subject.replace(/([^'\\]*(?:\\.[^'\\]*)*)'/g, "$1\\'");
    

    This is an example of Friedl's "unrolled loop" pattern:

    normal * (special normal *) *

    [^'\\]* is the "normal *" part; it gobbles up any number of characters other than single-quotes or backslashes. If the next character is a backslash, \\. ("special") consumes that and the next character (backslash, single-quote, or whatever) and [^'\\]* takes over again. Repeat as needed.

    The key point is that the regex never skips ahead and it never backtracks. If it sees a backslash, it always consumes that and the next character, so it never gets out of sync.

    0 讨论(0)
  • 2021-01-13 20:03

    You can write:

    var escaped = original.replace(/\\['\\]|'/g, function (s) {
        if (s == "'") return "\\'";
        else return s;
    });
    

    If there's a contiguous sequence of escaped-escapes, it skips them all. If at the end there's a "\'", then the quote is already escaped and is also skipped. If at the end there's a "'", the quote is escaped.

    0 讨论(0)
  • 2021-01-13 20:06

    Here's a solution

    /[^\\]\'|^\'/g
    
    0 讨论(0)
  • 2021-01-13 20:19

    If there are an even number of backslashes, they only quote each other. Thus a character is quoted if it has an odd number of preceding backslashes. Since JS doesn't support lookbehind, you'll need to capture the leading non-backslash and include it in the replacement.

    var escquote = /((^|[^\\])(\\\\)*)'/g
    "a ' b \' c \\' d".replace(escquote, "$1\\'")
    

    However, if this is for any sort of security purposes, it's the wrong approach for a number of reasons. Firstly, if you're doing this client side, it isn't secure. Second, quoting should be handled when data is sent to a subsystem using the methods provided by the subsystem. For example, if the data is going to a relational database, you should use prepared statements and parameterize the varying data. Prepared statement parameters aren't vulnerale to injection.

    0 讨论(0)
提交回复
热议问题