I have this string
java=10514;js=237;jsp=3995;web=5;xml=42
and I'd like to extract, in separate variables, the value numbers for each language, using javascript and a regular expression that is, for the "java" case, the follow
(?<=java=).*?(?=;|$)
I've tried this code
var myString = "java=10514;js=237;jsp=3995;web=5;xml=42";
var regexp_java = new RegExp('(?<=java=).*?(?=;|$)', 'g');
var ncloc_java = sonar_myString.match(regexp_java);
var regexp_js = new RegExp('(?<=js=).*?(?=;|$)', 'g');
var ncloc_js = sonar_myString.match(regexp_js);
var regexp_jsp = new RegExp('(?<=jsp=).*?(?=;|$)', 'g');
var ncloc_jsp = sonar_myString.match(regexp_jsp);
var regexp_web = new RegExp('(?<=web=).*?(?=;|$)', 'g');
var ncloc_web = sonar_myString.match(regexp_web);
var regexp_jsp = new RegExp('(?<=jsp=).*?(?=;|$)', 'g');
var ncloc_jsp = sonar_myString.match(regexp_jsp);
but it doesn't work.
Any suggestion will be appreciated and thank you in advance
I believe that you are using the wrong data structure here. Rather than trying to use individual variables for each language, you can instead use a hashmap. First split to the string on semicolon, and then stream that to get each language and value.
var input = "java=10514;js=237;jsp=3995;web=5;xml=42";
var map = {};
input.split(";").forEach(x => map[x.split("=")[0]] = x.split("=")[1]);
console.log(map);
Does it really need to be done with Regex? Anyways I'm providing you with 2 solutions.
const string = "java=10514;js=237;jsp=3995;web=5;xml=42";
let result1 = string.split(';').reduce((acc, curr) => {
let [key, value] = curr.split('=');
acc[key] = value;
return acc;
}, {});
console.log(result1);
let result2 = {};
let regex = /([a-z]+)\s*=\s*(\d+)/g;
let check;
while (check= regex.exec(string)) {
result2[check[1]] = check[2];
}
console.log(result2);
You don't have to create separate patterns and variables, Instead you can use 2 capture groups and then create an object with keys and values (assuming there are no duplicate keys)
\b(java|jsp?|web|xml)=([^;\s]+)
Explanation
\b A word boundary
(java|jsp?|web|xml) Match one of the alternatives
= Match literally
([^;\s]+) Capture group 2, match 1+ chars other than a whitespace char or ;
See a regex demo.
const myString = "java=10514;js=237;jsp=3995;web=5;xml=42";
const regex = /\b(java|jsp?|web|xml)=([^;\s]+)/g;
const kv = Object.fromEntries(
Array.from(
myString.matchAll(regex), m => [m[1], m[2]]
)
)
console.log(kv)
console.log(kv.java);
Related
Following up from this thread, im trying to make this work
JavaScript regular expression to match X digits only
string = '2016-2022'
re = /\d{4}/g
result = [...string.matchAll(re)]
This returns an array of two arrays. Is there a way to consolidate this into 1 array?
However it doesn't look like this is returning the desired results
I'm new to regular expression. What am I doing wrong?
this return an array of matches
result = string.match(re)
This is a function to parse the string encoding those two year values and return the inner years as items of an array:
let o = parseYearsInterval('2016-2022');
console.log(o);
function parseYearsInterval(encodedValue){
var myregexp = /(\d{4})-(\d{4})/;
var match = myregexp.exec(encodedValue);
if (match != null) {
let d1 = match[1];
let d2 = match[2];
//return `[${d1}, ${d2}]`;
let result = [];
result.push(d1);
result.push(d2);
return result;
} else {
return "not valid input";
}
}
I think there are better ways to do that like splitting the string against the "-" separator and return that value as is like:
console.log ( "2016-2022".split('-') )
Just do a split if you know that only years are in the string and the strucutre isn't changing:
let arr = str.split("-");
Question
string = '2016-2022'
re = /\d{4}/g
result = [...string.matchAll(re)]
This returns an array of two arrays. Is there a way to consolidate
this into 1 array?
Solution
You may simply flat the result of matchAll.
let string = '2016-2022'
let re = /\d{4}/g
console.log([...string.matchAll(re)].flat())
Alternative
If your structure is given like "yyyy-yyyy-yyyy" you might consider a simple split
console.log('2016-2022'.split('-'))
var str = '2016-2022';
var result = [];
str.replace(/\d{4}/g, function(match, i, original) {
result.push(match);
return '';
});
console.log(result);
I also wanted to mention, that matchAll does basicly nothing else then an while exec, that's why you get 2 arrays, you can do it by yourself in a while loop and just save back what you need
var result = [];
var matches;
var regexp = /\d{4}/g;
while (matches = regexp.exec('2016-2022')) result.push(matches[0]);
console.log(result);
I am looking for an alternative for this:
(?<=\.\d\d)\d
(Match third digit after a period.)
I'm aware I can solve it by using other methods, but I have to use a regular expression and more importantly I have to use replace on the string, without adding a callback.
Turn the lookbehind in a consuming pattern and use a capturing group:
And use it as shown below:
var s = "some string.005";
var rx = /\.\d\d(\d)/;
var m = s.match(/\.\d\d(\d)/);
if (m) {
console.log(m[1]);
}
Or, to get all matches:
const s = "some string.005 some string.006";
const rx = /\.\d\d(\d)/g;
let result = [], m;
while (m = rx.exec(s)) {
result.push(m[1]);
}
console.log( result );
An example with matchAll:
const result = Array.from(s.matchAll(rx), x=>x[1]);
EDIT:
To remove the 3 from the str.123 using your current specifications, use the same capturing approach: capture what you need and restore the captured text in the result using the $n backreference(s) in the replacement pattern, and just match what you need to remove.
var s = "str.123";
var rx = /(\.\d\d)\d/;
var res = s.replace(rx, "$1");
console.log(res);
I'm using named capturing groups to validate and extract data out of a product number. The format of the product number looks like this:
1102961D048.075
Chars 1-2 gender_code 11
Chars 1-6 style 110296
Chars 7-8 width_code 1D
Chars 9-11 color_code 048
Char 12 delimiter ignored
Chars 13-15 size_code 075
My current code looks like this:
const validateMpn = (mpn) => {
const regex = /(?<style>\d{6})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)
As gender_code and style overlap I'm not sure how to get them both. Therefore I have the following questions:
Is it possible to this with only one regular expression?
If yes, how could I accomplish this?
Sure, just place gender inside the style group:
const validateMpn = (mpn) => {
const regex = /(?<style>(?<gender>\d{2})\d{4})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)
I suggest just having separate capture groups for the first two and four following characters. Then, form the style by just concatenating together the first two capture groups:
var input = "1102961D048.075";
var regex = /(.{2})(.{4})(.{2})(.{3}).(.{3})/g;
var match = regex.exec(input);
console.log("gender_code: " + match[1]);
console.log("style: " + match[1] + match[2]);
As a style note, I prefer not using named capture groups, because they tend to result in a bloated regex which is hard to read.
Yes you can capture gender_code using positive look ahead using this regex,
(?=(..))(\d{6})(\d{1}[ABDE])(\d{3})\.(\d{3})
Regex Demo
This is named groups regex but will only work in Chrome browser
and named capture grouping will be available in ECMAScript 2018 and is only supported in Chrome as of now.
This JS demo will work in Chrome as that is the only one as of now supporting EcmaScript2018,
const validateMpn = (mpn) => {
const regex = /(?=(?<gender_code>\d\d))(?<style>\d{6})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi
const match = regex.exec(mpn)
if (!match) {
return null
}
return match.groups
}
const str1 = '1102961D048.075'
const str2 = '1200322A001.085'
const match1 = validateMpn(str1)
const match2 = validateMpn(str2)
console.log(match1)
console.log(match2)
I have the following RegExp myRegexp, that matches numbers in a string:
var myRegexp = new RegExp('[0-9]+');
Then I have the following code that extracts numbers from a string and returns an array:
var string = '123:456';
var nums = new Array();
while(myRegexp.test(string)) {
nums.length++;
nums[nums.length - 1] = RegExp.lastMatch;
string = RegExp.rightContext;
}
Should return an array of two elements: "123", and "456".
However, RegExp.lastMatch and RegExp.rightContext are deprecated/non-standard API, and not portable. How can I rewrite this logic using portable JS API?
Thanks,
To match all numbers in a string, you'd simply use string.match(/\d/g); to match all single digits in a separate array entry, or string.match(/\d+/g); to match as numbers. There's no need for any of the things you've tried to useā¦
let string = "2kdkane2kdkie83kdkdk303ldld";
let match = string.match(/\d+/g);
let match1 = string.match(/\d/g);
console.log('numbers:', match);
console.log('single digits:', match1);
Use the g flag to perform a global match which will find all matches without having to repeatedly test the string.
let s = '123:456'
const regexp = new RegExp(/\d+/g);
let nums = s.match(regexp);
console.log(nums);
I have a chain like this of get page
file.php?Valor1=one&Valor2=two&Valor3=three
I would like to be able to delete the get request parameter with only having the value of it. for example , remove two
Result
file.php?Valor1=one&Valor3=three
Try with
stringvalue.replace(new RegExp(value+"[(&||\s)]"),'');
Here's a regular expression that matches an ampersand (&), followed by a series of characters that are not equals signs ([^=]+), an equals sign (=), the literal value two and either the next ampersand or the end of line (&|$):
/&[^=]+=two(&|$)/
let input = 'file.php?&Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(/&[^=]+=two/, '');
console.log(output);
If you're getting the value to be removed from a variable:
let two = 'two';
let re = RegExp('&[^=]+=' + two + '(&|$)');
let input = 'file.php?&Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(re, '');
console.log(output);
In this case, you need to make sure that your variable value does not contain any characters that have special meaning in regular expressions. If that's the case, you need to properly escape them.
Update
To address the input string in the updated question (no ampersand before first parameter):
let one = 'one';
let re = RegExp('([?&])[^=]+=' + one + '(&?|$)');
let input = 'file.php?Valor1=one&Valor2=two&Valor3=three';
let output = input.replace(re, '$1');
console.log(output);
You can use RegExp constructor, RegExp, template literal &[a-zA-Z]+\\d+=(?=${remove})${remove}) to match "&" followed by "a-z", "A-Z", followed by one or more digits followed by "", followed by matching value to pass to .replace()
var str = "file.php?&Valor1=one&Valor2=two&Valor3=three";
var re = function(not) {
return new RegExp(`&[a-zA-Z]+\\d+=(?=${not})${not}`)
}
var remove = "two";
var res = str.replace(re(remove), "");
console.log(res);
var remove = "one";
var res = str.replace(re(remove), "");
console.log(res);
var remove = "three";
var res = str.replace(re(remove), "");
console.log(res);
I think a much cleaner solution would be to use the URLSearchParams api
var paramsString = "Valor1=one&Valor2=two&Valor3=three"
var searchParams = new URLSearchParams(paramsString);
//Iterate the search parameters.
//Each element will be [key, value]
for (let p of searchParams) {
if (p[1] == "two") {
searchParams.delete(p[0]);
}
}
console.log(searchParams.toString()); //Valor1=one&Valor3=three