Extract values with nested curly braces using regex in javascript - javascript

I have the below string in Javascript
var str = "β{;{9}/{(n-7)(n-8)}} ≤ β{;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}}";
I need to extract the text between curly braces starts with β symbol
i.e. β{text inside curly brases with {nested}}.
So from the above str I need to extract below two values based on β{ inside everything}
str1 = ";{9}/{(n-7)(n-8)}"`
str2 = ";{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}"
I tried many regex examples the closest I found working is a PHP example from this stackover flow link, but its not working in Javascript.
Please help me as pattern is having PHP syntax which is failing in Javascript
\{((?:[^{}]++|\{(?1)\})++)\}
Example 1 :
testinput = "β{test{test{12351}}{a+b}{1/2}}" // Input
testoutput = "{test{test{12351}}{a+b}{1/2}}β"; // output
Example 2:
testinput = "β{test}" // Input
testoutput = "{test}β"; // output

As JavaScript has no support for recursion in regex, the (?1) part of the regex is not valid (nor the double plus, but that is unrelated).
What you can do is first count the number of opening braces in the input, which gives you a ceiling on the nesting depth. Then construct a regex dynamically that supports that depth of nesting:
function extract(str) {
const count = str.match(/(?<!β){/g)?.length ?? 0;
const regex = RegExp("(?<=β{)[^{}]*" + "({[^{}]*".repeat(count) + "}[^{}]*)*".repeat(count) + "(?=})", "g");
return str.match(regex);
}
var str = "β{;{9}/{(n-7)(n-8)}} ≤ β{;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}}";
var parts = extract(str);
console.log(parts);

Related

Replace with a regex formula prop has quotation mark issue [duplicate]

This question already has answers here:
How do you use a variable in a regular expression?
(27 answers)
Closed 2 years ago.
So for example:
function(input){
var testVar = input;
string = ...
string.replace(/ReGeX + testVar + ReGeX/, "replacement")
}
But this is of course not working :)
Is there any way to do this?
const regex = new RegExp(`ReGeX${testVar}ReGeX`);
...
string.replace(regex, "replacement");
Update
Per some of the comments, it's important to note that you may want to escape the variable if there is potential for malicious content (e.g. the variable comes from user input)
ES6 Update
In 2019, this would usually be written using a template string, and the above code has been updated. The original answer was:
var regex = new RegExp("ReGeX" + testVar + "ReGeX");
...
string.replace(regex, "replacement");
You can use the RegExp object:
var regexstring = "whatever";
var regexp = new RegExp(regexstring, "gi");
var str = "whateverTest";
var str2 = str.replace(regexp, "other");
document.write(str2);
Then you can construct regexstring in any way you want.
You can read more about it here.
To build a regular expression from a variable in JavaScript, you'll need to use the RegExp constructor with a string parameter.
function reg(input) {
var flags;
//could be any combination of 'g', 'i', and 'm'
flags = 'g';
return new RegExp('ReGeX' + input + 'ReGeX', flags);
}
of course, this is a very naive example. It assumes that input is has been properly escaped for a regular expression. If you're dealing with user-input, or simply want to make it more convenient to match special characters, you'll need to escape special characters:
function regexEscape(str) {
return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
}
function reg(input) {
var flags;
//could be any combination of 'g', 'i', and 'm'
flags = 'g';
input = regexEscape(input);
return new RegExp('ReGeX' + input + 'ReGeX', flags);
}
You can create regular expressions in JS in one of two ways:
Using regular expression literal - /ab{2}/g
Using the regular expression constructor - new RegExp("ab{2}", "g") .
Regular expression literals are constant, and can not be used with variables. This could be achieved using the constructor. The stracture of the RegEx constructor is
new RegExp(regularExpressionString, modifiersString)
You can embed variables as part of the regularExpressionString. For example,
var pattern="cd"
var repeats=3
new RegExp(`${pattern}{${repeats}}`, "g")
This will match any appearance of the pattern cdcdcd.
if you're using es6 template literals are an option...
string.replace(new RegExp(`ReGeX${testVar}ReGeX`), "replacement")
You can always give regular expression as string, i.e. "ReGeX" + testVar + "ReGeX". You'll possibly have to escape some characters inside your string (e.g., double quote), but for most cases it's equivalent.
You can also use RegExp constructor to pass flags in (see the docs).
It's only necessary to prepare the string variable first and then convert it to the RegEx.
for example:
You want to add minLength and MaxLength with the variable to RegEx:
function getRegEx() {
const minLength = "5"; // for exapmle: min is 5
const maxLength = "12"; // for exapmle: man is 12
var regEx = "^.{" + minLength + ","+ maxLength +"}$"; // first we make a String variable of our RegEx
regEx = new RegExp(regEx, "g"); // now we convert it to RegEx
return regEx; // In the end, we return the RegEx
}
now if you change value of MaxLength or MinLength, It will change in all RegExs.
Hope to be useful. Also sorry about my English.
Here's an pretty useless function that return values wrapped by specific characters. :)
jsfiddle: https://jsfiddle.net/squadjot/43agwo6x/
function getValsWrappedIn(str,c1,c2){
var rg = new RegExp("(?<=\\"+c1+")(.*?)(?=\\"+c2+")","g");
return str.match(rg);
}
var exampleStr = "Something (5) or some time (19) or maybe a (thingy)";
var results = getValsWrappedIn(exampleStr,"(",")")
// Will return array ["5","19","thingy"]
console.log(results)
accepted answer doesn't work for me and doesn't follow MDN examples
see the 'Description' section in above link
I'd go with the following it's working for me:
let stringThatIsGoingToChange = 'findMe';
let flagsYouWant = 'gi' //simple string with flags
let dynamicRegExp = new RegExp(`${stringThatIsGoingToChange}`, flagsYouWant)
// that makes dynamicRegExp = /findMe/gi

Javascript - Use regex to find multiple occurrences of a pattern in a string

I have a string in this format
"{{abc}}, {{def}}, some text {{ghi}}, some other text {{jkl}}"
And I would like to replace each of {{...}} with some string based on what is ... (that comes out of json and not an issue) and stuck with what regex pattern to use. Closest I could come was to /{{(.*)}}/gi, but that returns the whole string as the same has {{ and }} at ends. Here's the code I have tried
let str = "{{abc}}, {{def}}, some text {{ghi}}, some other text {{jkl}}";
let regex = /{{(.*)}}/gi;
let result;
let indices = [];
let results = [];
while ((result = regex.exec(str))) {
indices.push(result.index);
results.push(result[0]);
}
Any help will be highly appreciated
This will do it: \{\{(.*?)\}\}
You need to escape the } via \, also set the non greedy operator ?
See: https://regex101.com/r/F9xdgx/2

How to move each character in a TextArea with ES6?

I need to go through a textarea to find and separate certain strings, such as:
Example 1) Separate the numbers from the text.
String "KAEeqk41KK EeqkKEKQ3 EKEK 43" - Result: [41, 3, 43]
Example 2) Count the blanks in the String.
OBS: _ = blank space
String "KAkeaekaek _ kea41 __ 3k1k31"
You could separate the numbers using match() and count some match using length, I'm not sure what do you mean with blanks but this example could be useful.
//var str = document.getElementById("textarea").value;//<-- probably somethig like this
var str = "KAEeqk41KK EeqkKEKQ3 EKEK 43";
var str2 = "KAkeaekaek _ kea41 __ 3k1k31"
var numbers = str.match(/[0-9]+/g)
var blanks = str2.match(/_| /g).length//<-- count spaces and _
console.log(numbers)
console.log(blanks)

Using RegExp to substring a string at the position of a special character

Suppose I have a sting like this: ABC5DEF/G or it might be ABC5DEF-15 or even just ABC5DEF, it could be shorter AB7F, or AB7FG/H.
I need to create a javascript variable that contains the substring only up to the '/' or the '-'. I would really like to use an array of values to break at. I thought maybe to try something like this.
...
var srcMark = array( '/', '-' );
var whereAt = new RegExp(srcMark.join('|')).test.str;
alert("whereAt= "+whereAt);
...
But this returns an error: ReferenceError: Can't find variable: array
I suspect I'm defining my array incorrectly but trying a number of other things I've been no more successful.
What am I doing wrong?
Arrays aren't defined like that in JavaScript, the easiest way to define it would be with:
var srcMark = ['/','-'];
Additionally, test is a function so it must be called as such:
whereAt = new RegExp(srcMark.join('|')).test(str);
Note that test won't actually tell you where, as your variable suggests, it will return true or false. If you want to find where the character is, use String.prototype.search:
str.search(new RegExp(srcMark.join('|'));
Hope that helps.
You need to use the split method:
var srcMark = Array.join(['-','/'],'|'); // "-|/" or
var regEx = new RegExp(srcMark,'g'); // /-|\//g
var substring = "222-22".split(regEx)[0] // "222"
"ABC5DEF/G".split(regEx)[0] // "ABC5DEF"
From whatever i could understand from your question, using this RegExp /[/-]/ in split() function will work.
EDIT:
For splitting the string at all special characters you can use new RegExp(/[^a-zA-Z0-9]/) in split() function.
var arr = "ABC5DEF/G";
var ans = arr.split(/[/-]/);
console.log(ans[0]);
arr = "ABC5DEF-15";
ans = arr.split(/[/-]/);
console.log(ans[0]);
// For all special characters
arr = "AB7FG/H";
ans = arr.split(new RegExp(/[^a-zA-Z0-9]/));
console.log(ans[0]);
You can use regex with String.split.
It will look something like that:
var result = ['ABC5DEF/G',
'ABC5DEF-15',
'ABC5DEF',
'AB7F',
'AB7FG/H'
].map((item) => item.split(/\W+/));
console.log(result);
That will create an Array with all the parts of the string, so each item[0] will contain the text till the / or - or nothing.
If you want the position of the special character (non-alpha-numeric) you can use a Regular Expression that matches any character that is not a word character from the basic Latin alphabet. Equivalent to [^A-Za-z0-9_], that is: \W
var pattern = /\W/;
var text = 'ABC5DEF/G';
var match = pattern.exec(text);
var position = match.index;
console.log('character: ', match[0]);
console.log('position: ', position);

Complex regex to split up a string

I need some help with a regex conundrum pls. I'm still getting to grips with it all - clearly not an expert!
Eg. Say I have a complex string like so:
{something:here}{examp.le:!/?foo|bar}BLAH|{something/else:here}:{and:here\\}(.)}
First of all I want to split the string into an array by using the pipe, so it is effectively like:
{something:here}{examp.le:!/?foo|bar}BLAH
and
{something/else:here}:{and:here\\}(.)}
But notice that there is a pipe within the curly brackets to ignore... so need to work out the regex expression for this. I was using indexOf originally, but because I now have to take into account pipes being within the curly brackets, it complicates things.
And it isn't over yet! I also then need to split each string into separate parts by what is within the curly brackets and not. So I end up with 2 arrays containing:
Array1
{something:here}
{examp.le:!/?foo|bar}
BLAH
Array2
{something/else:here}
:
{and:here\\}(.)}
I added a double slash before the first closing curly bracket as a way of saying to ignore this one. But cannot figure out the regex to do this.
Can anyone help?
Find all occurrences of "string in braces" or "just string", then iterate through found substrings and split when a pipe is encountered.
str = "{something:here}{examp.le:!/?foo|bar}BLAH|{something/else:here}:{and:here\\}(.)}"
var m = str.match(/{.+?}|[^{}]+/g)
var r = [[]];
var n = 0;
for(var i = 0; i < m.length; i++) {
var s = m[i];
if(s.charAt(0) == "{" || s.indexOf("|") < 0)
r[n].push(s);
else {
s = s.split("|");
if(s[0].length) r[n].push(s[0]);
r[++n] = [];
if(s[1].length) r[n].push(s[1]);
}
}
this expr will be probably better to handle escaped braces
var m = str.match(/{?(\\.|[^{}])+}?/g

Categories