How to find all appearances of text after a specific word? - javascript

I get a string like:
str = “Test/hello/filename/12345678/first
Hddhkhd
Hdhal
filename/1212abcd/second”
I want to get an array of the all strings that comes after “filename//“ and I know that after the “/“ there is an 8 letter word that I want to get.
In this case, I want to get an array that will be:
strArr = [“12345678”, “1212abcd”]
How do I solve this problem?

A regex that captures the 8 characters that immediately follow a literal "filename//":
/filename\/\/(.{8})/

Try use this regex first:
filename\/\w{8}
and after it, slice from the result by this regex:
\w{8}$
First you will get:
filename/12345678
filename/1212abcd
Second you will get :
12345678
1212abcd

You might also capture in a group matching 8 times not a forward slash or a newline after matching /filename
\bfilename\/([^\/\n]{8})
Regex demo
If you want to match 8 or more times you could use {8,} instead or if you want to match 1 or more times you could use a +.
If you don't want to match whitespace characters you could change the \n to \s
const regex = /filename\/([^\/\n]{8})/g;
const str = `Test/hello/filename/12345678/first
Hddhkhd
Hdhal
filename/1212abcd/second`;
let m;
while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
console.log(m[1]);
}

You can use the following code. It will match all characters after the filename/ until it encounters another /. After you get the matches in an array you can map it out and replace all the filename/ with '':
let a = /filename\/[^\/]+/g;
let b = 'Test/hello/filename/12345678/first Hddhkhd Hdhal filename/1212abcd/second';
let c = b.match(a).map(x=>x.replace('filename/',''));
console.log(c);

For explanation check this REGEX
var arr = "Test/hello/filename/12345678/first Hddhkhd Hdhal filename/1212abcd/second".match(/(?<=filename\/)(.*?)(?=\/)/g);
console.log(arr)
OR
For unsupported Lookbehinds browser use Array#map after regex
var arr = "Test/hello/filename/12345678/first Hddhkhd Hdhal filename/1212abcd/second".match(/filename\/(.*?)\//g).map(i=> i.split('/')[1]);
console.log(arr)

Related

Getting the content between two characters

So I have this (example) string: 1234VAR239582358X
And I want to get what's in between VAR and X. I can easily replace it using .replace(/VAR.*X/, "replacement");
But, how would I get the /VAR.*X/as a variable?
I think what you are looking for might be
string.match(/VAR(.*)X/)[1]
The brackets around the .* mark a group. Those groups are returned inside the Array that match creates :)
If you want to only replace what's in between "VAR" and "X" it would be
string.replace(/VAR(.*)X/, "VAR" + "replacement" + "X");
Or more generic:
string.replace(/(VAR).*(X)/, "$1replacement$2");
You can try use the RegExp class, new RegExp(`${VAR}.*X`)
You can store it as variable like this,
const pattern = "VAR.*X";
const reg = new RegExp(pattern);
Then use,
.replace(reg, "replacement");
If you
want to get what's in between VAR and X
then using .* would do the job for the given example string.
But note that is will match until the end of the string, and then backtrack to the first occurrence of X it can match, being the last occurrence of the X char in the string and possible match too much.
If you want to match only the digits, you can match 1+ digits in a capture group using VAR(\d+)X
const regex = /VAR(\d+)X/;
const str = "1234VAR239582358X";
const m = str.match(regex);
if (m) {
let myVariable = m[1];
console.log(myVariable);
}
Or you can match until the first occurrence of an X char using a negated character class VAR([^\r\nX]+)X
const regex = /VAR([^\r\nX]+)X/;
const str = "1234VAR239582358X";
const m = str.match(regex);
if (m) {
let myVariable = m[1];
console.log(myVariable);
}

regular expression replacement in JavaScript with some part remaining intact

I need to parse a string that comes like this:
-38419-indices-foo-7119-attributes-10073-bar
Where there are numbers followed by one or more words all joined by dashes. I need to get this:
[
0 => '38419-indices-foo',
1 => '7119-attributes',
2 => '10073-bar',
]
I had thought of attempting to replace only the dash before a number with a : and then using .split(':') - how would I do this? I don't want to replace the other dashes.
Imo, the pattern is straight-forward:
\d+\D+
To even get rid of the trailing -, you could go for
(\d+\D+)(?:-|$)
Or
\d+(?:(?!-\d|$).)+
You can see it here:
var myString = "-38419-indices-foo-7119-attributes-10073-bar";
var myRegexp = /(\d+\D+)(?:-|$)/g;
var result = [];
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
result.push(match[1]);
match = myRegexp.exec(myString);
}
console.log(result);
// alternative 2
let alternative_results = myString.match(/\d+(?:(?!-\d|$).)+/g);
console.log(alternative_results);
Or a demo on regex101.com.
Logic
lazy matching using quantifier .*?
Regex
.*?((\d+)\D*)(?!-)
https://regex101.com/r/WeTzF0/1
Test string
-38419-indices-foo-7119-attributes-10073-bar-333333-dfdfdfdf-dfdfdfdf-dfdfdfdfdfdf-123232323-dfsdfsfsdfdf
Matches
Further steps
You need to split from the matches and insert into your desired array.

Regex for matching only first of two same characters in a string

I have these two strings: "1-2" and "1--2".
I would like to have a regex that would match only the first occurrence of the hyphen in both strings, such that the split would then be: [1,2] and [1,-2]. How would I achieve this, since I have been wracking my brain for too long on this now?
EDIT: The two strings can also occur in the same string such that: "1-2-1--2". Therefore a single regular expression covering both cases would be in order.
You can use this split with a word boundary before -:
let s='1-2-1--2'
let arr = s.split(/\b-/)
console.log(arr)
//=> [1, 2, 1, -2)
You can use simple split(), but with replacement. For example,
var str = '1-2-1--2';
var numArr = str.replace(/--/g, '-~') // The tilde (~) have no mean, this is a charceter for mark a negative number
.split('-')
.map(function(n) { return Number(n.replace('~', '-')); });
console.log(numArr);
I think you're looking for something like this:
(-?[0-9]+)-(-?[0-9]+)
where the first and the second group could have a negative sign
UPDATE:
based on your edit, this implementation would do the job:
var str = '-1--2-2--34-1';
var regex = /(-?\d+)-?/g;
var matches = [];
while((match = regex.exec(str))) {
matches.push(match[1]);
}
console.log(matches);
I prefer using split, but it's fine if you only want to use RegEx.

Javascript split function not correct worked with specific regex

I have a problem. I have a string - "\,str\,i,ing" and i need to split by comma before which not have slash. For my string - ["\,str\,i", "ing"]. I'm use next regex
myString.split("[^\],", 2)
but it's doesn't worked.
Well, this is ridiculous to avoid the lack of lookbehind but seems to get the correct result.
"\\,str\\,i,ing".split('').reverse().join('').split(/,(?=[^\\])/).map(function(a){
return a.split('').reverse().join('');
}).reverse();
//=> ["\,str\,i", "ing"]
Not sure about your expected output but you are specifying string not a regex, use:
var arr = "\,str\,i,ing".split(/[^\\],/, 2);
console.log(arr);
To split using regex, wrap your regex in /..../
This is not easily possible with js, because it does not support lookbehind. Even if you'd use a real regex, it would eat the last character:
> "xyz\\,xyz,xyz".split(/[^\\],/, 2)
["xyz\\,xy", "xyz"]
If you don't want the z to be eaten, I'd suggest:
var str = "....";
return str.split(",").reduce(function(res, part) {
var l = res.length;
if (l && res[l-1].substr(-1) == "\\" || l<2)
// ^ ^^ ^
// not the first was escaped limit
res[l-1] += ","+part;
else
res.push(part);
return;
}, []);
Reading between the lines, it looks like you want to split a string by , characters that are not preceded by \ characters.
It would be really great if JavaScript had a regular expression lookbehind (and negative lookbehind) pattern, but unfortunately it does not. What it does have is a lookahead ((?=) )and negative lookahead ((?!)) pattern. Make sure to review the documentation.
You can use these as a lookbehind if you reverse the string:
var str,
reverseStr,
arr,
reverseArr;
//don't forget to escape your backslashes
str = '\\,str\\,i,ing';
//reverse your string
reverseStr = str.split('').reverse().join('');
//split the array on `,`s that aren't followed by `\`
reverseArr = reverseStr.split(/,(?!\\)/);
//reverse the reversed array, and reverse each string in the array
arr = reverseArr.reverse().map(function (val) {
return val.split('').reverse().join('');
});
You picked a tough character to match- a forward slash preceding a comma is apt to disappear while you pass it around in a string, since '\,'==','...
var s= 'My dog, the one with two \\, blue \\,eyes, is asleep.';
var a= [], M, rx=/(\\?),/g;
while((M= rx.exec(s))!= null){
if(M[1]) continue;
a.push(s.substring(0, rx.lastIndex-1));
s= s.substring(rx.lastIndex);
rx.lastIndex= 0;
};
a.push(s);
/* returned value: (Array)
My dog
the one with two \, blue \,eyes
is asleep.
*/
Find something which will not be present in your original string, say "###". Replace "\\," with it. Split the resulting string by ",". Replace "###" back with "\\,".
Something like this:
<script type="text/javascript">
var s1 = "\\,str\\,i,ing";
var s2 = s1.replace(/\\,/g,"###");
console.log(s2);
var s3 = s2.split(",");
for (var i=0;i<s3.length;i++)
{
s3[i] = s3[i].replace(/###/g,"\\,");
}
console.log(s3);
</script>
See JSFiddle

Regex to grab strings between square brackets

I have the following string: pass[1][2011-08-21][total_passes]
How would I extract the items between the square brackets into an array? I tried
match(/\[(.*?)\]/);
var s = 'pass[1][2011-08-21][total_passes]';
var result = s.match(/\[(.*?)\]/);
console.log(result);
but this only returns [1].
Not sure how to do this.. Thanks in advance.
You are almost there, you just need a global match (note the /g flag):
match(/\[(.*?)\]/g);
Example: http://jsfiddle.net/kobi/Rbdj4/
If you want something that only captures the group (from MDN):
var s = "pass[1][2011-08-21][total_passes]";
var matches = [];
var pattern = /\[(.*?)\]/g;
var match;
while ((match = pattern.exec(s)) != null)
{
matches.push(match[1]);
}
Example: http://jsfiddle.net/kobi/6a7XN/
Another option (which I usually prefer), is abusing the replace callback:
var matches = [];
s.replace(/\[(.*?)\]/g, function(g0,g1){matches.push(g1);})
Example: http://jsfiddle.net/kobi/6CEzP/
var s = 'pass[1][2011-08-21][total_passes]';
r = s.match(/\[([^\]]*)\]/g);
r ; //# => [ '[1]', '[2011-08-21]', '[total_passes]' ]
example proving the edge case of unbalanced [];
var s = 'pass[1]]][2011-08-21][total_passes]';
r = s.match(/\[([^\]]*)\]/g);
r; //# => [ '[1]', '[2011-08-21]', '[total_passes]' ]
add the global flag to your regex , and iterate the array returned .
match(/\[(.*?)\]/g)
I'm not sure if you can get this directly into an array. But the following code should work to find all occurences and then process them:
var string = "pass[1][2011-08-21][total_passes]";
var regex = /\[([^\]]*)\]/g;
while (match = regex.exec(string)) {
alert(match[1]);
}
Please note: i really think you need the character class [^\]] here. Otherwise in my test the expression would match the hole string because ] is also matches by .*.
'pass[1][2011-08-21][total_passes]'.match(/\[.+?\]/g); // ["[1]","[2011-08-21]","[total_passes]"]
Explanation
\[ # match the opening [
Note: \ before [ tells that do NOT consider as a grouping symbol.
.+? # Accept one or more character but NOT greedy
\] # match the closing ] and again do NOT consider as a grouping symbol
/g # do NOT stop after the first match. Do it for the whole input string.
You can play with other combinations of the regular expression
https://regex101.com/r/IYDkNi/1
[C#]
string str1 = " pass[1][2011-08-21][total_passes]";
string matching = #"\[(.*?)\]";
Regex reg = new Regex(matching);
MatchCollection matches = reg.Matches(str1);
you can use foreach for matched strings.

Categories