Regex containg a variable [duplicate] - javascript

This question already has answers here:
Javascript Regex: How to put a variable inside a regular expression? [duplicate]
(9 answers)
Closed 8 years ago.
Regex and variables seem to be a current issue here, yet I didn't find an answer to my problem.
It is quite simple, i am using a noSQL database system for javascript called nedb. pretty neat by the way. GitHub link
Here is the part that matters for us :
// Finding all planets whose name contain the substring 'ar' using a regular expression
db.find({ planet: /ar/ }, function (err, docs) {
// docs contains Mars and Earth
});
as you see, the expression /ar/ means "containing the substring ar", which is classic regex.
What I want is replacing ar by a variable (the result of a user search).
Like this :
var search = ‘ar'; //taken from an HTML form
db.find ({planet : ‘/‘ + search + ‘/‘}, fonction (err,docs) {
}
This unfortunately does not work. Neither does :
var search = ‘/ar/';
db.find ({planet : search}, fonction (err,docs) {
}
Do you have any ideas ? Might seem prettu obvious to you, but i am losing my mind on this issue aha !
thank you guys

Use the RegExp constructor :
db.find({ planet: new RegExp(yourString) }, function (err, docs) {
If your string can be anything, you'd better escape it. See this related answer then.

You need to use the RegExp constructor, but this alone is not enough (. would be "any character", ? would mean the previous character is optional and / would break your regex, as well as all the other regular regex keywords and characters).
You can avoid this by using a regex escaping function (such aspreg_quote from PHPJS) which will escape them:
db.find({ planet: new RegExp(preg_quote(searchString, '/')) }, function (err, docs) {

Related

NodeJS Regex match 4 digit number in string with 'OR' words [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 3 years ago.
I need to regex string with a year inside. Template is 'Year-<4 digits>-"high OR low"-level'.
I've built this regex: /Year-\d{4}-\b(low|high)\b-level/gi;
In online regex testers my strings pass the check. Sample code:
const template = /Year-\d{4}-\b(low|high)\b-level/gi;
const txtArr = ['Year-2019-low-level', 'Year-2019-high-level', 'Year-low-level', 'Year-high-level', 'Year-2018-low-level', 'Year-2018-low-level']
for (const s of txtArr) {
console.log(template.test(s), s);
}
I expect 2 of sample strings to not pass, but 4 should pass. But they dont - only 2 of them pass. Also in browser console they don't pass. Tried in FF and Chrome. Can't understand why.
Also, if I copy the string that is not passing the match and just make
console.log(template.test('Year-2018-low-level'), 'Year-2018-low-level');
it passes! I've got only one idea: looks like in every iteration of loop something is not reset in regex, and it keeps something in memory, that is not letting match pass.
P.S. I even copied the same string which must pass the test to array, like that:
const txtArr = ['Year-2019-low-level', 'Year-2019-low-level', 'Year-2019-low-level', 'Year-2019-low-level', 'Year-2019-low-level', 'Year-2019-low-level']
and the results are true-false-true-false-true... Why? And how to fix?
I found an explanation here: https://siderite.dev/blog/careful-when-reusing-javascript-regexp.html
"The moral of the story is to be careful of constructs like _reg.test(input);
when _reg is a global regular expression. It will attempt to match from the index of the last match in any previous string."
So the problem comes from the way the global statement is treated.
The author of the blog also describes the very same problem you have:
"Here is a case that was totally weird. Imagine a javascript function that returns an array of strings based on a regular expression match inside a for loop. In FireFox it would return half the number of items that it should have."
What you could do to avoid this problem is either not using the global keyword, or instanciate a new regex at each iteration:
const txtArr = ['Year-2019-low-level', 'Year-2019-high-level', 'Year-low-level', 'Year-high-level', 'Year-2018-low-level', 'Year-2018-low-level']
for (const s of txtArr) {
console.log(/Year-\d{4}-\b(low|high)\b-level/gi.test(s), s);
}
An alternative is to use !!s.match(template) instead of template.test(s), so you don't need to modify your regex.
Working example: https://codesandbox.io/s/zen-carson-z9cq6
An explanation to the weird behavior:
The RegExp object keeps track of the lastIndex where a match occurred,
so on subsequent matches it will start from the last used index,
instead of 0.
from this StackOverflow question: Why does a RegExp with global flag give wrong results?
I changed your regex and its working, with this one:
const template = /Year-\d{4}-(low|high)-level/

How to build a regex w/ new RegExp() [duplicate]

This question already has answers here:
Why do regex constructors need to be double escaped?
(5 answers)
Closed 6 years ago.
Have an array of local storage keys that looks something like this
[
'$gl-user',
'$gl-date-preference::22'
'$gl-date-preference::28'
'$gl-mg-filters::22::1'
'$gl-mg-filters::22::8'
]
First ::_number_ represents the storeId.
Second ::_number_ can
represents any additional identifier.
Trying to build a function that takes a storeId and returns all keys that match that storeId. So if 22 was passed in to that function it would return
[
'$gl-date-preference::22',
'$gl-mg-filters::22::1',
'$gl-mg-filters::22::8'
]
Here is my first attempt. Copying this into the console returns null every time but I do not understand why.
var regex = new RegExp('^[$\w\d\-]+\:\:' + '22');
'$gl-mg-filters::22'.match(regex);
Any assistance in getting this regex to work, or ideas on a better solution would be greatly appreciated. Thank you!
Your regex isn't matching, because you're only escaping with the slashes inside of the string. Instead, you should be escaping it twice, e.g.:
var regex = new RegExp('^[$\\w\\d\\-]+\\:\\:' + '22');
'$gl-mg-filters::22'.match(regex);
Your initial attempt would try to compile ^[$wd-]+::22 into a Regex.

What does "matches x and remembers the match" means in regexp [duplicate]

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 8 years ago.
Pardon me if it seems to be trivial but just to understand regexps:
As said here with character (x) :
(x) matches x and remembers
First part "matches" I can understand but the second part "remembers" is a bit tedious for me to understand.
Can someone please help in explaining it in much easier way?
It's called capturing group. Using backreference ($1, $2, ...), you can reference it in the substitution string:
'R2D5'.replace(/(\d)/g, '$1$1')
// => "R22D55"
You can also use backreference (\1, \2, ...) in the pattern:
'ABBCCDEF'.match(/(.)\1/g) // to match consecutive character
// => ["BB", "CC"]
And you will get additional parameters when you use replacement function:
'R2D5'.replace(/(\d)/g, function(fullMatch, capture1) {
return (parseInt(capture1) + 1).toString();
})
// => "R3D6"
In most regex stuff you can specify a "capturing group" and recall them later:
"something".replace(/so(me)/, '$1 ')
Here, the capturing group is (me) - the result will be me thing

javascript: is there any elegant way to check if string contains any of characters given in an array [duplicate]

This question already has answers here:
Call a function if a string contains any items in an array
(3 answers)
Closed 8 years ago.
I have a string in my JavaScript code (plain JavaScript, no jQuery or any other libs involved). And also I have an array which contains characters to be found in a string. I need to check if string contains any of those characters. Of course, it could be done with temporary variable like found and array elements iteration.
But is there any way to write nice and compact code? Just in case, I use ES5 (IE9+).
I want to achieve something like
var str = "Here is the string",
chars = ['z','g'];
if (str.containsAnyOf(chars)) {
...
}
What is the best way to write that piece of code?
You can use Array.prototype.some, like this
if (chars.some(function(c) { return str.indexOf(c) !== -1; })) {
// Atleast one of the characters is present
};
Consider using regular expression:
var str = "Here is the string",
chars = ['z','g'];
// constructs the following regexp: /[zg]/
if (new RegExp("[" + chars.join('') + "]").test(str)) {
alert("Contains!");
}

replace '\n' in javascript [duplicate]

This question already has answers here:
How do I replace all occurrences of a string in JavaScript?
(78 answers)
Fastest method to replace all instances of a character in a string [duplicate]
(14 answers)
Closed 1 year ago.
I'm trying to do replace in JavaScript using:
r = "I\nam\nhere";
s = r.replace("\n"," ");
But instead of giving me
I am here
as the value of s,
It returns the same.
Where's the problem??
As stated by the others the global flag is missing for your regular expression. The correct expression should be some thing like what the others gave you.
var r = "I\nam\nhere";
var s = r.replace(/\n/g,' ');
I would like to point out the difference from what was going on from the start.
you were using the following statements
var r = "I\nam\nhere";
var s = r.replace("\n"," ");
The statements are indeed correct and will replace one instance of the character \n. It uses a different algorithm. When giving a String to replace it will look for the first occurrence and simply replace it with the string given as second argument. When using regular expressions we are not just looking for the character to match we can write complicated matching syntax and if a match or several are found then it will be replaced. More on regular expressions for JavaScript can be found here w3schools.
For instance the method you made could be made more general to parse input from several different types of files. Due to differences in Operating system it is quite common to have files with \n or \r where a new line is required. To be able to handle both your code could be rewritten using some features of regular expressions.
var r = "I\ram\nhere";
var s = r.replace(/[\n\r]/g,' ');
use s = r.replace(/\\n/g," ");
Get a reference:
The "g" in the javascript replace code stands for "greedy" which means the replacement should happen more than once if possible
The problem is that you need to use the g flag to replace all matches, as, by default, replace() only acts on the first match it finds:
var r = "I\nam\nhere",
s = r.replace(/\n/g,' ');
To use the g flag, though, you'll have to use the regular expression approach.
Incidentally, when declaring variables please use var, otherwise the variables you create are all global, which can lead to problems later on.
.replace() needs the global match flag:
s = r.replace(/\n/g, " ");
It's working for me:
var s = r.split('\\n').join(' ');
replaceAll() is relative new, not supported in all browsers:
r = "I\nam\nhere";
s = r.replaceAll("\n"," ");
You can use:
var s = r.replace(/\n/g,' ').replace(/\r/g,' ');
because diferents SO use diferents ways to set a "new line", for example: Mac Unix Windows, after this, you can use other function to normalize white spaces.
Just use \\\n to replace it will work.
r.replace("\\\n"," ");
The solution from here worked perfect for me:
r.replace(/=(\r\n|\n|\r)/gm," ");

Categories

Resources