Get all occurrences of value in between two patterns in JavaScript - javascript

I have to the following long string. How do I extract all the values that are in between "url=" and "," so that I then have the following array?
"load("#bazel_tools//tools/build_defs/repo:http.bzl","http_jar")definclude_java_deps():http_jar(name="com_google_inject_guice",sha256="b378ffc35e7f7125b3c5f3a461d4591ae1685e3c781392f0c854ed7b7581d6d2",url="https://repo1.maven.org/maven2/com/google/inject/guice/4.0/guice-4.0.jar",)http_jar(name="org_sonatype_sisu_inject_cglib",sha256="42e1dfb26becbf1a633f25b47e39fcc422b85e77e4c0468d9a44f885f5fa0be2",url="https://repo1.maven.org/maven2/org/sonatype/sisu/inject/cglib/2.2.1-v20090111/cglib-2.2.1-v20090111.jar",)http_jar(name="javax_inject_javax_inject",sha256="91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff",url="https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar",)"
[
https://repo1.maven.org/maven2/com/google/inject/guice/4.0/guice-4.0.jar,
https://repo1.maven.org/maven2/org/sonatype/sisu/inject/cglib/2.2.1-v20090111/cglib-2.2.1-v20090111.jar,
https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar
]
I've tried the following, but it only gives me the first occurrence of it, but I need them all. Thanks!
var arr = contents.split('url=').pop().split(',')
for(i in arr) {
console.log(arr[i]);
}

You can solve this by using a Regular Expression
const regEx = /(?:url=")([^,]+)(?:",)/gm;
const string = 'load("#bazel_tools//tools/build_defs/repo:http.bzl","http_jar")definclude_java_deps():http_jar(name="com_google_inject_guice",sha256="b378ffc35e7f7125b3c5f3a461d4591ae1685e3c781392f0c854ed7b7581d6d2",url="https://repo1.maven.org/maven2/com/google/inject/guice/4.0/guice-4.0.jar",)http_jar(name="org_sonatype_sisu_inject_cglib",sha256="42e1dfb26becbf1a633f25b47e39fcc422b85e77e4c0468d9a44f885f5fa0be2",url="https://repo1.maven.org/maven2/org/sonatype/sisu/inject/cglib/2.2.1-v20090111/cglib-2.2.1-v20090111.jar",)http_jar(name="javax_inject_javax_inject",sha256="91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff",url="https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar",)'
const matches = string.matchAll(regEx);
for (const match of matches) {
console.log(match[1]);
}
Or with string methods
const string = 'load("#bazel_tools//tools/build_defs/repo:http.bzl","http_jar")definclude_java_deps():http_jar(name="com_google_inject_guice",sha256="b378ffc35e7f7125b3c5f3a461d4591ae1685e3c781392f0c854ed7b7581d6d2",url="https://repo1.maven.org/maven2/com/google/inject/guice/4.0/guice-4.0.jar",)http_jar(name="org_sonatype_sisu_inject_cglib",sha256="42e1dfb26becbf1a633f25b47e39fcc422b85e77e4c0468d9a44f885f5fa0be2",url="https://repo1.maven.org/maven2/org/sonatype/sisu/inject/cglib/2.2.1-v20090111/cglib-2.2.1-v20090111.jar",)http_jar(name="javax_inject_javax_inject",sha256="91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff",url="https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar",)'
const arr = string.split('url="');
const urls = arr
.filter((subStr) => subStr.includes('https://'))
.map((subStr) => subStr.split('",)')[0]);
console.log(urls);
The RegEx solution is of course widely more flexible.
Be aware that Regular Expressions can be "unsafe" which means they might have extremely long evaluation times depending on the input. Libraries like this can help you detect these

Related

Javascript replace string with list from array

I have a string that is a normal sentence. I need to replace the characters in the string if they are found in a given array. For example,
const arr = ["(model: Audi)", "(model: Kia)"];
if the string is:
"How is your (model: Audi) today?";
The result should be "How is your Audi today?".
Is there a way to do this with regex? I read somewhere that regex has better performance. I've tried looping thru the array then replacing the characters but I couldnt get it working and my solution would have nested loops due to the given string
const arr = ["(model: Audi)", "(model: Kia)"];
let string = "How is your (model: Audi) today?";
for (let data of arr){
string = string.replace(data, data.split(": ")[1].replace(")",""))
}
console.log(string);
Well, this is the simplest I have managed to do.
However, I myself kind of consider it a bad solution.
Let me know if it helps at all...
const myString = "How is your (model: Audi) today?";
const arr = ["(model: Audi)", "(model: Kia)"];
arr.forEach(item => {
const part = item.match(/\w+\)$/)[0];
const subPart = part.substring(0, part.length - 1);
if (myString.includes(item))
console.log(myString.replace(item, subPart));
});

Looking for one regex to replace my string

I have problem with regex and need some help.
Current I have url has type
/search/:year/:month/:day/xxxx with :month and :day maybe exist or not . Now I need replace /search/:year/:month/:day patern on my url with empty string. Meaning get remain of url part. So this is some example below
1.'/search/2017/02/03/category/gun' => '/category/gun'
2.'/search/2017/02/03/' => '/'
3.'/search/2017/01/category/gun' => '/category/gun/'
4.'/search/2017/category/gun/' => '/category/gun/'
5.'/search/2018/?category=gun&type%5B%5D=sendo' => '/?category=gun&type%5B%5D=sendo/'
I try to use regex = /^\/search\/((?:\d{4}))(?:\/((?:\d|1[012]|0[1-9])))?(?:\/((?:[0-3]\d)))/
But it is failed for case /search/2017/category/gun/
const regex = /^\/search\/((?:\d{4}))(?:\/((?:\d|1[012]|0[1-9])))?(?:\/((?:[0-3]\d)))/
const testLink = [
'/search/2017/02/03/category/gun/',
'/search/2017/01/category/gun/',
'/search/2017/category/gun/',
'/search/2017/02/03/category/gun/',
'/search/2018/?category=gun&type%5B%5D=sendo'
]
testLink.forEach((value, i) => {
console.log(value.replace(regex, ''))
console.log('-------------------')
})
Use this regex pattern (\/search\/.*\d+)(?=\/)
Demo
const regex = /(\/search\/.*\d+)(?=\/)/g;
const testLink = [
'/search/2017/02/03/category/gun/',
'/search/2017/01/category/gun/',
'/search/2017/',
'/search/2017/02/03/category/gun/',
'/search/2018/?category=gun&type%5B%5D=sendo'
]
testLink.forEach((value, i) => {
console.log(value.replace(regex, ''))
console.log('-------------------')
})
Splitting on the following pattern seems to work:
\d{4}(?:/\d{2})*
This would place the target you want as the second element in the split array, with the first portion being what precedes the year-digit portions of the path.
input = '/search/2017/02/03/category/gun';
parts = input.split(/\d{4}(?:\/\d{2})*/);
console.log(parts[1]);
console.log('/search/2017/02/03'.split(/\d{4}(?:\/\d{2})*/)[1]);
console.log('/search/2017/01/category/gun'.split(/\d{4}(?:\/\d{2})*/)[1]);
console.log('/search/2017/category/gun/'.split(/\d{4}(?:\/\d{2})*/)[1]);
Whether you do or do not expect a final trailing path separator is not entirely clear. In any case, the above answered can be modified per that expectation.
Here's one way:
strings = [
'/search/2017/02/03/category/gun',
'/search/2017/02/03/',
'/search/2017/01/category/gun',
'/search/2017/category/gun/',
]; for (var i = 0; i < strings.length; i++) {
alert(strings[i].replace(/\/search\/[0-9\/]+(\/)(category\/[^\/$]+)?.*/,'$1$2'));
}
you can use the same regex but revers the order of this part (?:\d|1[012]|0[1-9])
as following (?:\d|1[012]|0[1-9]) and make last group optional as following ((?:[0-3]\d)))?
const regex = /^\/search\/((?:\d{4}))(?:\/((?:0[1-9]|1[012]|\d)))?(?:\/((?:[0-3]\d)))?/
const testLink = [
'/search/2017/02/03/category/gun/',
'/search/2017/01/category/gun/',
'/search/2017/category/gun/',
'/search/2017/02/03/category/gun/'
]
output
/category/gun/
/category/gun/
/category/gun/
/category/gun/
if you are sure of date format so you can simplify your exp to be ^\/search\/\d{4}(?:\/\d{1,2}){0,2}

How to rewrite this RegExp to not use deprecated API?

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);

Dynamically compare accuracy of regex patterns for match

Supposing I have two regexes and both match a string, but one of them matches it in a stricter way, is there a way to figure that out programmatically?
For example, I'm matching this string:
/path/on/file/system
and I have the following two regular expressions:
const opt1 = /\/path\/on/;
const opt2 = /\/path/;
I can see with my eyes that opt1 is stricter, but how can javascript know about that?
Is converting the regex to a string and checking for character length a good measure of strictness?
You can implement this function by:
Sorting your regular expressions by length.
loop through your sorted regular expressions array to check if there is a match
then return the most strict matching element.
function check(arrayOfRegEx, str) {
//sort the regex array by length
var sortedArr = arrayOfRegEx.sort(function(a, b) {
return a.toString().length - b.toString().length || a.toString().localeCompare(b);
});
let mostStrict = '';
sortedArr.forEach(function(reg) {
if(new RegExp((reg.toString()).replace(/\\/g, "").substring(1)).test(str)) {
mostStrict = reg;
}
});
return mostStrict;
}
var result = check([/\/path/, /\/test\/test/, /\/path\/on/], '/path/on/file/system');
console.log(result); // returns /\/path\/on/
And of course you can tweak this function to fit your needs

How can I capture word by Regex

I would like to capture the array key from a string.
Here are my words: message[0][generic][0][elements][0][default_action][url]...
I want to capture the array keys after message[0][generic][0][elements][0], and the expected results are default_action and url etc.
I have tried following patterns but not work.
message\[0\]\[generic\]\[0\]\[elements\]\[0\](?=\[(\w+)\]): it captures default_action only;
\[(\w+)\]: it captures all array keys, but includes 0, generic, elements...
Is there any regex pattern for JavaScript that make the result array inverse, like [url, default_action]?
You can replace unwanted part of a string,and then get all other keys.
var string = 'message[0][generic][0][elements][0][default_action][url][imthird]';
var regexp = /message\[0\]\[generic\]\[0\]\[elements\]\[0\]/
var answer = string.replace(regexp,'').match(/[^\[\]]+/g)
console.log(answer);
To extract any number of keys and reverse the order of the elements in resulting array:
str = "message[0][generic][0][elements][0][default_action][url]";
res = str.match(/\[([^\d\]]+)\](?=\[[^\d\]]*\]|$)/g)
.map(function(s) { return s.replace(/[\[\]]/g, "") })
.reverse();
console.log(res);
The solution using String.prototype.split() and Array.prototype.slice() functions:
var s = 'message[0][generic][0][elements][0][default_action][url]...',
result = s.split(/\]\[|[\[\]]/g).slice(-3,-1);
console.log(result);

Categories