JSHint "Bad or unnecessary escaping." Do double slashes beginning/end matter? - javascript

I'm storing some RegExps in an Object as strings, but getting the above error message.
I believe this is because they aren't prefixed with / or suffixed with / - as I'm running them into a new RegExp() constructor, as the script allows users to define RegExps, so I want them all to be dynamic.
var patterns = {
email: '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$',
url: '[-a-zA-Z0-9#:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9#:%_\+.~#?&//=]*)',
number: '^[-+]?[0-9]*\.?[0-9]+$',
empty: '^\\s*$'
};
There's the above strings.
To fix them I can do this and / / them:
var patterns = {
email: '/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/',
url: '/[-a-zA-Z0-9#:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9#:%_\+.~#?&//=]*)/',
number: '/^[-+]?[0-9]*\.?[0-9]+$',
empty: '/^\\s*$/'
};
But when called via new RegExp() surely they'll do this (for example):
var reg = new RegExp(patterns.empty);
/**
* reg = //^\\s*$//
*/
With double slashes. My question as a bit of a RegExp beginner, is do these double slashes matter? Can it be fixed another way. JSHint is complaining because it's not a "real" RegExp.
I can also remove them from strings and store as true RegExps, but again I need them to be dynamic. Any help appreciated.

The problem is that the backslash character (\) is used both for escaping special characters in string literals (e.g. \n is interpreted as a single newline character, and \\ as a single backslash character), and it's used in escaping special characters in regular expressions.
So when a string literal is used for a regexp, and you need the regexp to see \, you need to escape the backslash and include \\ in the string literal. Specifically, in email you need \\. rather than \.. E.g.
email: '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$'
Alternatively, you could put the regular expressions in /.../ rather than '...' (or '/.../'). Then string literal escaping doesn't apply, and you don't need to double the slashes. E.g.
email: /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
In the latter case, you also don't need new RegExp(patterns.email), since patterns.email is already a RegExp object.

Related

document.getElementById('input-ID').value - for an input (!) - returns undefined [duplicate]

In the regex below, \s denotes a space character. I imagine the regex parser, is going through the string and sees \ and knows that the next character is special.
But this is not the case as double escapes are required.
Why is this?
var res = new RegExp('(\\s|^)' + foo).test(moo);
Is there a concrete example of how a single escape could be mis-interpreted as something else?
You are constructing the regular expression by passing a string to the RegExp constructor.
\ is an escape character in string literals.
The \ is consumed by the string literal parsing…
const foo = "foo";
const string = '(\s|^)' + foo;
console.log(string);
… so the data you pass to the RegEx compiler is a plain s and not \s.
You need to escape the \ to express the \ as data instead of being an escape character itself.
Inside the code where you're creating a string, the backslash is a javascript escape character first, which means the escape sequences like \t, \n, \", etc. will be translated into their javascript counterpart (tab, newline, quote, etc.), and that will be made a part of the string. Double-backslash represents a single backslash in the actual string itself, so if you want a backslash in the string, you escape that first.
So when you generate a string by saying var someString = '(\\s|^)', what you're really doing is creating an actual string with the value (\s|^).
The Regex needs a string representation of \s, which in JavaScript can be produced using the literal "\\s".
Here's a live example to illustrate why "\s" is not enough:
alert("One backslash: \s\nDouble backslashes: \\s");
Note how an extra \ before \s changes the output.
As has been said, inside a string literal, a backslash indicates an escape sequence, rather than a literal backslash character, but the RegExp constructor often needs literal backslash characters in the string passed to it, so the code should have \\s to represent a literal backslash, in most cases.
A problem is that double-escaping metacharacters is tedious. There is one way to pass a string to new RegExp without having to double escape them: use the String.raw template tag, an ES6 feature, which allows you to write a string that will be parsed by the interpreter verbatim, without any parsing of escape sequences. For example:
console.log('\\'.length); // length 1: an escaped backslash
console.log(`\\`.length); // length 1: an escaped backslash
console.log(String.raw`\\`.length); // length 2: no escaping in String.raw!
So, if you wish to keep your code readable, and you have many backslashes, you may use String.raw to type only one backslash, when the pattern requires a backslash:
const sentence = 'foo bar baz';
const regex = new RegExp(String.raw`\bfoo\sbar\sbaz\b`);
console.log(regex.test(sentence));
But there's a better option. Generally, there's not much good reason to use new RegExp unless you need to dynamically create a regular expression from existing variables. Otherwise, you should use regex literals instead, which do not require double-escaping of metacharacters, and do not require writing out String.raw to keep the pattern readable:
const sentence = 'foo bar baz';
const regex = /\bfoo\sbar\sbaz\b/;
console.log(regex.test(sentence));
Best to only use new RegExp when the pattern must be created on-the-fly, like in the following snippet:
const sentence = 'foo bar baz';
const wordToFind = 'foo'; // from user input
const regex = new RegExp(String.raw`\b${wordToFind}\b`);
console.log(regex.test(sentence));
\ is used in Strings to escape special characters. If you want a backslash in your string (e.g. for the \ in \s) you have to escape it via a backslash. So \ becomes \\ .
EDIT: Even had to do it here, because \\ in my answer turned to \.

Why do these two JavaScript regular expression produce different results? [duplicate]

In the regex below, \s denotes a space character. I imagine the regex parser, is going through the string and sees \ and knows that the next character is special.
But this is not the case as double escapes are required.
Why is this?
var res = new RegExp('(\\s|^)' + foo).test(moo);
Is there a concrete example of how a single escape could be mis-interpreted as something else?
You are constructing the regular expression by passing a string to the RegExp constructor.
\ is an escape character in string literals.
The \ is consumed by the string literal parsing…
const foo = "foo";
const string = '(\s|^)' + foo;
console.log(string);
… so the data you pass to the RegEx compiler is a plain s and not \s.
You need to escape the \ to express the \ as data instead of being an escape character itself.
Inside the code where you're creating a string, the backslash is a javascript escape character first, which means the escape sequences like \t, \n, \", etc. will be translated into their javascript counterpart (tab, newline, quote, etc.), and that will be made a part of the string. Double-backslash represents a single backslash in the actual string itself, so if you want a backslash in the string, you escape that first.
So when you generate a string by saying var someString = '(\\s|^)', what you're really doing is creating an actual string with the value (\s|^).
The Regex needs a string representation of \s, which in JavaScript can be produced using the literal "\\s".
Here's a live example to illustrate why "\s" is not enough:
alert("One backslash: \s\nDouble backslashes: \\s");
Note how an extra \ before \s changes the output.
As has been said, inside a string literal, a backslash indicates an escape sequence, rather than a literal backslash character, but the RegExp constructor often needs literal backslash characters in the string passed to it, so the code should have \\s to represent a literal backslash, in most cases.
A problem is that double-escaping metacharacters is tedious. There is one way to pass a string to new RegExp without having to double escape them: use the String.raw template tag, an ES6 feature, which allows you to write a string that will be parsed by the interpreter verbatim, without any parsing of escape sequences. For example:
console.log('\\'.length); // length 1: an escaped backslash
console.log(`\\`.length); // length 1: an escaped backslash
console.log(String.raw`\\`.length); // length 2: no escaping in String.raw!
So, if you wish to keep your code readable, and you have many backslashes, you may use String.raw to type only one backslash, when the pattern requires a backslash:
const sentence = 'foo bar baz';
const regex = new RegExp(String.raw`\bfoo\sbar\sbaz\b`);
console.log(regex.test(sentence));
But there's a better option. Generally, there's not much good reason to use new RegExp unless you need to dynamically create a regular expression from existing variables. Otherwise, you should use regex literals instead, which do not require double-escaping of metacharacters, and do not require writing out String.raw to keep the pattern readable:
const sentence = 'foo bar baz';
const regex = /\bfoo\sbar\sbaz\b/;
console.log(regex.test(sentence));
Best to only use new RegExp when the pattern must be created on-the-fly, like in the following snippet:
const sentence = 'foo bar baz';
const wordToFind = 'foo'; // from user input
const regex = new RegExp(String.raw`\b${wordToFind}\b`);
console.log(regex.test(sentence));
\ is used in Strings to escape special characters. If you want a backslash in your string (e.g. for the \ in \s) you have to escape it via a backslash. So \ becomes \\ .
EDIT: Even had to do it here, because \\ in my answer turned to \.

why does this js RegExp test return true? [duplicate]

The regex allows chars that are: alphanumeric, space, '-', '_', '&', '()' and '/'
this is the expression
[\s\/\)\(\w&-]
I have tested this in various online testers and know it works, I just can't get it to work correctly in code. I get sysntax errors with anything I try.. any suggestions?
var programProductRegex = new RegExp([\s\/\)\(\w&-]);
You can use the regular expression syntax:
var programProductRegex = /[\s\/\)\(\w&-]/;
You use forward slashes to delimit the regex pattern.
If you use the RegExp object constructor you need to pass in a string. Because backslashes are special escape characters inside JavaScript strings and they're also escape characters in regular expressions, you need to use two backslashes to do a regex escape inside a string. The equivalent code using a string would then be:
var programProductRegex = new RegExp("[\\s\\/\\)\\(\\w&-]");
All the backslashes that were in the original regular expression need to be escaped in the string to be correctly interpreted as backslashes.
Of course the first option is better. The constructor is helpful when you obtain a string from somewhere and want to make a regular expression out of it.
var programProductRegex = new RegExp(userInput);
If you are using a String and want to escape characters like (, you need to write \\( (meaning writing backslash, then the opening parenthesis => escaping it).
If you are using the RegExp object, you only need one backslash for each character (like \()
Enclose your regex with delimiters:
var programProductRegex = /[\s\/)(\w&-]/;

Javascript RegExp not escaping parenthesis properly. Why? [duplicate]

In the regex below, \s denotes a space character. I imagine the regex parser, is going through the string and sees \ and knows that the next character is special.
But this is not the case as double escapes are required.
Why is this?
var res = new RegExp('(\\s|^)' + foo).test(moo);
Is there a concrete example of how a single escape could be mis-interpreted as something else?
You are constructing the regular expression by passing a string to the RegExp constructor.
\ is an escape character in string literals.
The \ is consumed by the string literal parsing…
const foo = "foo";
const string = '(\s|^)' + foo;
console.log(string);
… so the data you pass to the RegEx compiler is a plain s and not \s.
You need to escape the \ to express the \ as data instead of being an escape character itself.
Inside the code where you're creating a string, the backslash is a javascript escape character first, which means the escape sequences like \t, \n, \", etc. will be translated into their javascript counterpart (tab, newline, quote, etc.), and that will be made a part of the string. Double-backslash represents a single backslash in the actual string itself, so if you want a backslash in the string, you escape that first.
So when you generate a string by saying var someString = '(\\s|^)', what you're really doing is creating an actual string with the value (\s|^).
The Regex needs a string representation of \s, which in JavaScript can be produced using the literal "\\s".
Here's a live example to illustrate why "\s" is not enough:
alert("One backslash: \s\nDouble backslashes: \\s");
Note how an extra \ before \s changes the output.
As has been said, inside a string literal, a backslash indicates an escape sequence, rather than a literal backslash character, but the RegExp constructor often needs literal backslash characters in the string passed to it, so the code should have \\s to represent a literal backslash, in most cases.
A problem is that double-escaping metacharacters is tedious. There is one way to pass a string to new RegExp without having to double escape them: use the String.raw template tag, an ES6 feature, which allows you to write a string that will be parsed by the interpreter verbatim, without any parsing of escape sequences. For example:
console.log('\\'.length); // length 1: an escaped backslash
console.log(`\\`.length); // length 1: an escaped backslash
console.log(String.raw`\\`.length); // length 2: no escaping in String.raw!
So, if you wish to keep your code readable, and you have many backslashes, you may use String.raw to type only one backslash, when the pattern requires a backslash:
const sentence = 'foo bar baz';
const regex = new RegExp(String.raw`\bfoo\sbar\sbaz\b`);
console.log(regex.test(sentence));
But there's a better option. Generally, there's not much good reason to use new RegExp unless you need to dynamically create a regular expression from existing variables. Otherwise, you should use regex literals instead, which do not require double-escaping of metacharacters, and do not require writing out String.raw to keep the pattern readable:
const sentence = 'foo bar baz';
const regex = /\bfoo\sbar\sbaz\b/;
console.log(regex.test(sentence));
Best to only use new RegExp when the pattern must be created on-the-fly, like in the following snippet:
const sentence = 'foo bar baz';
const wordToFind = 'foo'; // from user input
const regex = new RegExp(String.raw`\b${wordToFind}\b`);
console.log(regex.test(sentence));
\ is used in Strings to escape special characters. If you want a backslash in your string (e.g. for the \ in \s) you have to escape it via a backslash. So \ becomes \\ .
EDIT: Even had to do it here, because \\ in my answer turned to \.

javascript: some problem with compiler interpreting // as comments in regex

I've got this regular expression for validating phone numbers
^(\+?|(\(\+?[0-9]{1,3}\))|)([ 0-9.//-]|\([ 0-9.//-]+\))+((x|X|((e|E)(x|X)(t|T)))([ 0-9.//-]|\([ 0-9.//-]+\)))?$
I dugged it out from my C#/vb library and now i want to translate it into javascript. But it has syntax error (i suspect it is something due to the // characters). my attempt:
$IsPhone = function (input) {
var regex = new window.RegExp("^$|^(\+?|(\(\+?[0-9]{1,3}\))|)([ 0-9.//-]|\([ 0-9.//-]+\))+((x|X|((e|E)(x|X)(t|T)))([ 0-9.//-]|\([ 0-9.//-]+\)))?$", "");
return regex.test(input.trim());
};
alert($IsPhone("asd"));
Your problem has nothing to do with comments. You're just mixing up the two different ways of creating RegExp objects.
When you create a RegExp object in JavaScript code, you either write it as a string literal which you pass to a RegExp constructor, or as a regex literal. Because string literals support backslash-escape sequences like \n and \", any actual backslash in the string has to be escaped, too. So, whenever you need to escape a regex metacharacter like ( or +, you have to use two backslashes, like so:
var r0 = "^$|^(\\+?|(\\(\\+?[0-9]{1,3}\\))|)([ 0-9./-]|\\([ 0-9./-]+\\))+((x|X|((e|E)(x|X)(t|T)))([ 0-9./-]|\\([ 0-9./-]+\\)))?$";
var regex0 = new RegExp(r0, "");
The forward-slash has no special meaning, either to regexes or strings. The only reason you ever have to escape forward-slashes is because they're used as the delimiter for regex literals. You use backslashes to escape the forward-slashes just like you do with regex metacharacters like \( or \+, or the backslash itself: \\. Here's the regex-literal version of your regex:
var regex1 = /^$|^(\+?|(\(\+?[0-9]{1,3}\))|)([ 0-9.\/-]|\([ 0-9.\/-]+\))+((x|X|((e|E)(x|X)(t|T)))([ 0-9.\/-]|\([ 0-9.\/-]+\)))?$/;
from Errors translating regex from .NET to javascript
The backslash character in JavaScript
strings is an escape character, so the
backslashes you have in your string
are escaping the next character for
the string, not for the regular
expression. So right near the
beginning, in your "^(+?, the
backslash there just escapes the + for
the string (which it doesn't need),
and what the regexp sees is just a raw
+ with nothing to repeat. Hence the error.

Categories

Resources