How to concat two javascript variables and regex expression - javascript

I want to be able to concat two variables with a regular expression in the middle.
e.g.
var t1 = "Test1"
var t2 = "Test2"
var re = new RegEx(t1 + "/.*/" + t2);
So the result I want is an expression that matches this..
"Test1 this works Test2"
How do I get a result where I am able to match any text that has Test1 and Test2 on the ends?

Try this (I use nodejs):
> var t1 = "Test1"
> var t2 = "Test2"
> var re = new RegExp('^' + t1 + '.*' + t2 + '$')
> re
/^Test1.*Test2$/
> re.test("Test1 this works Test2")
true
Note
.* as stated in comments, this means any character repeated from 0 to ~
the slashes are automagically added when calling the RegExp constructor, but you can't have nested unprotected slashes delimiters
to ensure Test1 is at the beginning, i put ^ anchor, and for Test2 at the end, I added $ anchor
the regex constructor is not ReGex but RegExp (note the trailing p)

The RegExp constructor takes care of adding the forward slashes for you.
var t1 = "Test1";
var t2 = "Test2";
var re = new RegExp(t1 + ".*" + t2);
re.test("Test1 some_text Test2"); // true

You don't need regex:
var t1 = 'Test1';
var t2 = 'Test2';
var test = function(s) { return s.startsWith(t1) && s.endsWith(t2); };
console.log(test('Test1 this works Test2'));
console.log(test('Test1 this does not'));

if you know the beginning and the end you can enforce that:
var re = new RegExp("^" + t1 + ".*" + t2 + "$");

Take care that the value of the two variables do not contain any special regex characters, or transform those values to escape any special regex characters.
Of course, also make sure that the regex in between matches what you want it to :-)

Related

Regex not working for multiple characters

I want to search and replace special characters of markdown (viz \`*_{}[]()#+.!|-) from the given string.
I am able to make it work in C# easily since there is verbatim # but Javascript not getting what's the issue. It seems something to do with /g , I read in another post which asked to use replaceAll but I could not find that method for string
C# version
string test = #"B
*H*
C
**AB**";
Console.WriteLine ("Input " + test);
var pattern = #"[\\`*_{}\[\]()#+-.!]";
var _1 = Regex.Replace (test, "\r?\n", "<br/>");
var out_ = Regex.Replace (_1, pattern, m => #"\" + m.Value);
Console.WriteLine ("Output " + out_);
Typescript Version
const regexM = new RegExp(/[\\\`\*\_\{\}\[\]\(\)#\+-\.!\|]/g, 'm');
var input = `B
*H*
C
**AB**`;
var inputString = input.replace(regexM, function (y: any) { return "\\" + y; });
if (/\r|\n/.exec(inputString))
{
inputString = inputString .replace(/\r?\n/g, "<br/>");
}
inputString = inputString.replace(regexM, function (x: any)
{
return "\\" + x;
});
Expected: B <br/>\*H\*<br/>C<br/>\*\*AB\*\*
I am getting B <br/>\*H*<br/>C<br/>**AB**
You may use
const regexM = /[\\`*_{}[\]()#+.!|-]/g;
var input = `B
*H*
C
**AB**`;
var inputString = input.replace(regexM, "\\$&");
inputString = inputString.replace(/\r?\n/g, "<br/>");
console.log(inputString);
// => B <br/>\*H\*<br/>C<br/>\*\*AB\*\*
NOTE:
The - in the regexM regex forms a range, you need to either escape it or - as in the code above - put it at the end of the character class
Rather than using callback methods, in order to reference the whole match, you may use the $& placeholder in a string replacement pattern
When you define the regex using a regex literal, there is only one backslash needed to form a regex escape, so const regexM = /[\\`*_{}[\]()#+.!|-]/g is equal to const regexM = new RegExp("[\\\\`*_{}[\\]()#+.!|-]", "g")
There is no need to check if there is a line break char or not with if (/\r|\n/.exec(inputString)), just run .replace.

I need a help for regexp in javascript code

var str = "^" + "/post/\d+" + "$";
var regex = new RegExp(str);
var flag = regex.test("/post/3333");
console.log(flag) // -> false
console.log(regex) // -> /^\/post\/d+$/
I'm expecting the result becomes true, but it results in false.
I think the problem is "\" is added automatically before "/" when RegExp instance is created.
How am I supposed to write in order to make it work?
You don't need the new RegExp constructor and string
Here example
var regex = /post\/\d+$/;
var flag = regex.test("/post/3333");
I removed ^ flag, because regex will not work with this format of input "website/post/3333"
Here's a more specific regular expression to match the format of /post/####:
var regex = /\/post\/[0-9]+$/;
var flag = regex.test("/post/3333");
This will test for the string /post/ followed by one or more digits, occurring at the end of the line.
Likewise:
var regex = /\/post\/[0-9]{4}$/;
var flag = regex.test("/post/3333");
will test for the string /post/ followed by 4 digits, occurring at the end of the line.

Regular expression to remove more than one continuous "--"

I have two requirements, first, I want to replace the "-" symbol in both beginning and end of the text with an empty value. Second, if there are any continuous "-" symbols they should be replaced with a single "-" symbol.
If possible please provide the code for both the requirements in a single pattern.
CODE:
//1.)
// replace more than 1 "-" in b
// Expected Output : -asdas-sadf-asdasd-ju
var a = "--asdas-sadf----asdasd---ju";
a = a.replace(/-{2,}/,"");
//alert(a);
//2.)
// remove last "-" and starting "-" from b that is "das-" - after das needs to be removed
// Expected output : welcome/asasdgrd/asd-ast-yret-das/456
var b = "-welcome/asasdgrd/asd-ast-yret-das-/456"
b = b.replace(/[-$]/,"");
//alert(b);
Fiddler Link:
http://jsfiddle.net/nj5j0yeq/1/
You need to use capturing groups.
var s = "--asdas-sadf----asdasd---ju";
alert(s.replace(/^-+|-+$|(-)+/gm, "$1"));
^-+|-(?!.*?-)|(-){2,}
You can try this.Replace by $1.See demo.
https://regex101.com/r/jV9oV2/8
You can check even time of -- and can replace with odd -
var a = "--asdas-sadf----asdasd---ju";
var b= a.split("--").join("-");
var c = b;
var d = c.split("--").join("-");
console.log(d);
or `var res = str.split(/^-+$|(-)+/).join("");
console.log(res);
`

How can I loop through string and replace all periods except the last one?

Let's say I have a string like this:
var test = my.long.file.name.zip
I am getting the total number of periods in this string with javascript like so:
var dots = (test.match(/\./g) || []).length;
I would then like to replace all of the periods in the string with underscores if there is more than one period in the string.
if(dots>"1"){
var newname = test.replace(/\./g, "_");
console.log(newname);
}
The problem is that this is replacing all of the periods. I would like to keep the last on intact. So what I would like the newname variable to read as would be:
my_long_file_name.zip
My guess is that I should use $.each() somehow to iterate over all except the last one to change the name. How should I do this?
You dont necessarily need a loop, you could do it with a more complex regex, which uses a positive lookahead
The regex /\.(?=.*\.)/g finds periods, but only where there is a subsequent period somewhere further along, which means the last one is not matched.
window.onload = function(){
var input = "my.long.file.name.zip"
var result = input.replace(/\.(?=.*\.)/g,'_')
alert(result);
}
Consider splitting the string on '.', then re-joining all but the last with '_':
var test = "my.long.file.name.zip";
parts = test.split('.');
var plen = parts.length;
if (plen > 1) {
test = parts.slice(0, plen - 1).join('_') +
"." +
parts[plen - 1];
}
console.log(test);
a lookahead group in regex will work:
var test = 'my.long.file.name.zip';
var result = test.replace(/\.(?=[^.]*\.)/g, '_');
alert(result);
this matches a dot followed by ('anything but dot' and another dot), replacing only what is outside the group
var test = 'my.long.file.name.zip';
var last_index = test.lastIndexOf('.');
var newname = test;
if (-1 !== last_index) {
newname = test.replace(/\./g, '_');
newname = newname.substring(0, last_index).concat('.', newname.substring(last_index + 1));
}
console.log(newname);

How can I concatenate regex literals in JavaScript?

Is it possible to do something like this?
var pattern = /some regex segment/ + /* comment here */
/another segment/;
Or do I have to use new RegExp() syntax and concatenate a string? I'd prefer to use the literal as the code is both more self-evident and concise.
Here is how to create a regular expression without using the regular expression literal syntax. This lets you do arbitary string manipulation before it becomes a regular expression object:
var segment_part = "some bit of the regexp";
var pattern = new RegExp("some regex segment" + /*comment here */
segment_part + /* that was defined just now */
"another segment");
If you have two regular expression literals, you can in fact concatenate them using this technique:
var regex1 = /foo/g;
var regex2 = /bar/y;
var flags = (regex1.flags + regex2.flags).split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
var regex3 = new RegExp(expression_one.source + expression_two.source, flags);
// regex3 is now /foobar/gy
It's just more wordy than just having expression one and two being literal strings instead of literal regular expressions.
Just randomly concatenating regular expressions objects can have some adverse side effects. Use the RegExp.source instead:
var r1 = /abc/g;
var r2 = /def/;
var r3 = new RegExp(r1.source + r2.source,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '') +
(r1.multiline ? 'm' : ''));
console.log(r3);
var m = 'test that abcdef and abcdef has a match?'.match(r3);
console.log(m);
// m should contain 2 matches
This will also give you the ability to retain the regular expression flags from a previous RegExp using the standard RegExp flags.
jsFiddle
I don't quite agree with the "eval" option.
var xxx = /abcd/;
var yyy = /efgh/;
var zzz = new RegExp(eval(xxx)+eval(yyy));
will give "//abcd//efgh//" which is not the intended result.
Using source like
var zzz = new RegExp(xxx.source+yyy.source);
will give "/abcdefgh/" and that is correct.
Logicaly there is no need to EVALUATE, you know your EXPRESSION. You just need its SOURCE or how it is written not necessarely its value. As for the flags, you just need to use the optional argument of RegExp.
In my situation, I do run in the issue of ^ and $ being used in several expression I am trying to concatenate together! Those expressions are grammar filters used accross the program. Now I wan't to use some of them together to handle the case of PREPOSITIONS.
I may have to "slice" the sources to remove the starting and ending ^( and/or )$ :)
Cheers, Alex.
Problem If the regexp contains back-matching groups like \1.
var r = /(a|b)\1/ // Matches aa, bb but nothing else.
var p = /(c|d)\1/ // Matches cc, dd but nothing else.
Then just contatenating the sources will not work. Indeed, the combination of the two is:
var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false
The solution:
First we count the number of matching groups in the first regex, Then for each back-matching token in the second, we increment it by the number of matching groups.
function concatenate(r1, r2) {
var count = function(r, str) {
return str.match(r).length;
}
var numberGroups = /([^\\]|^)(?=\((?!\?:))/g; // Home-made regexp to count groups.
var offset = count(numberGroups, r1.source);
var escapedMatch = /[\\](?:(\d+)|.)/g; // Home-made regexp for escaped literals, greedy on numbers.
var r2newSource = r2.source.replace(escapedMatch, function(match, number) { return number?"\\"+(number-0+offset):match; });
return new RegExp(r1.source+r2newSource,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '')
+ (r1.multiline ? 'm' : ''));
}
Test:
var rp = concatenate(r, p) // returns /(a|b)\1(c|d)\2/
rp.test("aadd") // Returns true
Providing that:
you know what you do in your regexp;
you have many regex pieces to form a pattern and they will use same flag;
you find it more readable to separate your small pattern chunks into an array;
you also want to be able to comment each part for next dev or yourself later;
you prefer to visually simplify your regex like /this/g rather than new RegExp('this', 'g');
it's ok for you to assemble the regex in an extra step rather than having it in one piece from the start;
Then you may like to write this way:
var regexParts =
[
/\b(\d+|null)\b/,// Some comments.
/\b(true|false)\b/,
/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|length|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/,
/(\$|jQuery)/,
/many more patterns/
],
regexString = regexParts.map(function(x){return x.source}).join('|'),
regexPattern = new RegExp(regexString, 'g');
you can then do something like:
string.replace(regexPattern, function()
{
var m = arguments,
Class = '';
switch(true)
{
// Numbers and 'null'.
case (Boolean)(m[1]):
m = m[1];
Class = 'number';
break;
// True or False.
case (Boolean)(m[2]):
m = m[2];
Class = 'bool';
break;
// True or False.
case (Boolean)(m[3]):
m = m[3];
Class = 'keyword';
break;
// $ or 'jQuery'.
case (Boolean)(m[4]):
m = m[4];
Class = 'dollar';
break;
// More cases...
}
return '<span class="' + Class + '">' + m + '</span>';
})
In my particular case (a code-mirror-like editor), it is much easier to perform one big regex, rather than a lot of replaces like following as each time I replace with a html tag to wrap an expression, the next pattern will be harder to target without affecting the html tag itself (and without the good lookbehind that is unfortunately not supported in javascript):
.replace(/(\b\d+|null\b)/g, '<span class="number">$1</span>')
.replace(/(\btrue|false\b)/g, '<span class="bool">$1</span>')
.replace(/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/g, '<span class="keyword">$1</span>')
.replace(/\$/g, '<span class="dollar">$</span>')
.replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation">$1</span>')
It would be preferable to use the literal syntax as often as possible. It's shorter, more legible, and you do not need escape quotes or double-escape backlashes. From "Javascript Patterns", Stoyan Stefanov 2010.
But using New may be the only way to concatenate.
I would avoid eval. Its not safe.
You could do something like:
function concatRegex(...segments) {
return new RegExp(segments.join(''));
}
The segments would be strings (rather than regex literals) passed in as separate arguments.
You can concat regex source from both the literal and RegExp class:
var xxx = new RegExp(/abcd/);
var zzz = new RegExp(xxx.source + /efgh/.source);
Use the constructor with 2 params and avoid the problem with trailing '/':
var re_final = new RegExp("\\" + ".", "g"); // constructor can have 2 params!
console.log("...finally".replace(re_final, "!") + "\n" + re_final +
" works as expected..."); // !!!finally works as expected
// meanwhile
re_final = new RegExp("\\" + "." + "g"); // appends final '/'
console.log("... finally".replace(re_final, "!")); // ...finally
console.log(re_final, "does not work!"); // does not work
No, the literal way is not supported. You'll have to use RegExp.
the easier way to me would be concatenate the sources, ex.:
a = /\d+/
b = /\w+/
c = new RegExp(a.source + b.source)
the c value will result in:
/\d+\w+/
I prefer to use eval('your expression') because it does not add the /on each end/ that ='new RegExp' does.

Categories