开发者

Help with javascript regex to add backslashes to certain characters if doesn't exist already

开发者 https://www.devze.com 2023-02-14 03:31 出处:网络
I have another Javascript regex conundrum... (apologies if this is a bit long-winded - hard to explain!)

I have another Javascript regex conundrum... (apologies if this is a bit long-winded - hard to explain!)

I have a script which sends a string to a popup window (all characters are encoded when they are sent, so all backslashes are preserved). In the popup it has several text input boxes, and also a 'summary' span which displays what is in all the input boxes, and is updated whenever a keyup is detected. Then when the user is finished, they click a button which sends the updated summary string back to the opener.

The requirement is that backslashes are prepended automatically to the following characters: \ / }, so the user doesn't need to do this themselves. Currently I have code that strips out any backslashes in the input boxes, but the summary adds them where appropriate.

Eg. if this string is sent to the popup: foobar\\batz\/hi Then it will look like this in the summary: foobar\\batz\/hi and like this in the input box: foobar\batz/hi. If you then edit the string like this in the input box: foobar\batz/hiya, then it looks like this in the summary: foobar\\batz\/hiya. So far so good... but if you attempt to type this in the input box: foobar\\ba开发者_Python百科tz/hiya, then it looks like this in the summary: foobar\\\batz\/hiya. It should look like this: foobar\\\\batz\/hiya

This is down to the existing code (that is run on every 'kepup'). It basically needs a regex to look at the string, and add backslashes to \ / or } if they do not exist already. This requires a negative lookbehind to check for pre-existing backslashes (but javascript cannot do negative lookbehinds). I thought I had cracked this by reversing the string first (using a custom function), and doing a negative lookahead, then reversing the string again, like this:

var thisBoxVal = $(this).val();
thisBoxVal = reverseStr(thisBoxVal);
thisBoxVal = thisBoxVal.replace(/(\}|\/|\\(?!\\))/g,"$1\\");
thisBoxVal = reverseStr(thisBoxVal);

However, I can now see where the problem lies. When encountering the first (or 2nd because it is reversed) of a double backslash, it adds the extra backslash. But because the 2nd backslash has this first backslash there already, it won't add it.

I also have concerns about memory allocation every time a string is reversed. This is because I learned that javascript strings are immutable, which I believe has the unfortunate effect of allocating more memory every time a string is reversed. Doing this on every keystroke (as it needs to do this to update the summary line whenever the input box is altered) may cause some issues(...?).

Is there any other way of doing this? Preferably with just some regex, and no reversing...

So to summarise, the requirement is to create a regex replace that searches a string for any of these chars \ / } and add an 'escaping' backslash before them (if an escaping backslash doesn't exist already). So it should have the intelligence when encountering more than one backslash in a row, to escape each one (note that I'm not updating the actual input box, but a variable which I use to update the summary).

I need a regex master's help!


You could escape anything that is not a letter, digit, space or backslash.

string=string.replace(/([^\w \\])/g,'\\$1')


The following should solve it:

thisBoxVal = thisBoxVal.replace/((\}|\/(?!\\))|\\)/g,"$1\\");

But the requirement seems strange. Why should \\ translate into \\\\, but \{ into \{. This also means if the string foo\\{bar is in the summary, it is foo\{bar in the input box, and when you save that again, it becomes foo\{bar in the summary. That sounds like an error. If I were you I'd just drop the negative lookahead altogether..


You can check for existing backslash escapes by checking for an even number of backslashes before the characters to escape, in which case an additional backslash is needed:

thisBoxVal = thisBoxVal.replace(/(^|[^\\])((?:\\{2})*)(\\(?=[^\\/}]|$)|[/}])/g, '$1$2\\$3');

The regexp breaks down as follows:

  • (^|[^\\]): before the escapes, match something that isn't an escape (start-of-string or non-\)
  • ((?:\\{2})*): an even number of escape characters. In each pair, the first escapes the second, so we don't want to touch these.
  • (\\(?=[^\\/}]|$)|[/}]): the character to escape:
    • \\(?=[^\\/}]|$): a backslash, followed by something that isn't escapable, which is either a character that isn't escapable ([^\\/}], otherwise this backslash would itself be escaping the character that follows) or the end-of-string.
    • [/}]: an escapable character, other than an backslash.

Sample string:

thisBoxVal = "sl0: \\;  sl1: /;  sl2: \\\\\\;  nosl0: \\\\;  nosl1: \\{;  sl3: \\";

Print value: "sl0: \; sl1: /; sl2: \\\; nosl0: \\; nosl1: \{; sl3: \"
Result of replace: "sl0: \\; sl1: \/; sl2: \\\\; nosl0: \\; nosl1: \{; sl3: \\"

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号