js Remove a part from a parameter which doesnt fit a pattern - javascript

const regex = /[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}/gm;
let m;
while ((m = regex.exec(tweet.text)) !== null) {
let newClass = tweet.text.replace(/[^1-9a-zA-Z]{3}-[^1-9a-zA-Z]{3}-[^1-9a-zA-Z]{3}/g, '');
console.log(`Found match: ${newClass}`);
};
when tweet.text = "123.qwe.456 test" I still get the same output but I want to remove anything which doesnt fit the pattern
/[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}/
any ideas?

You can use capture groups to extract exactly what gets matched in your string and then replace your original variable with this value. Something like
const regex = /([1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3})/
let match = tweet.text.match(regex)
tweet.text = match[1]

Instead of replace, you can get the match instead
\b[1-9a-zA-Z]{3}([-.])[1-9a-zA-Z]{3}\1[1-9a-zA-Z]{3}\b
Explanation
\b A word boundary
[1-9a-zA-Z]{3} Match 3 times any of the listed (Note that 1-9 does not match a 0)
([-.]) Capture in group 1 either an - or .
[1-9a-zA-Z]{3} Match 3 times any of the listed
\1 Back reference to group 1, match the same as captured in group 1
[1-9a-zA-Z]{3} Match 3 times any of the listed
\b A word boundary
Regex demo

const regex = /[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}-[1-9a-zA-Z]{3}/gm;
let m;
while ((m = regex.exec(tweet.text)) !== null) {
console.log(`Found match: ${m[0]}`);
figured the solution

Related

Regex to get substring between first and last occurence

Assume there is the string
just/the/path/to/file.txt
I need to get the part between the first and the last slash: the/path/to
I came up with this regex: /^(.*?).([^\/]*)$/, but this gives me everything in front of the last slash.
Don't use [^/]*, since that won't match anything that contains a slash. Just use .* to match anything:
/(.*?)\/(.*)\/(.*)/
Group 1 = just, Group 2 = the/path/to and Group 3 = file.txt.
The regex should be \/(.*)\/. You can check my below demo:
const regex = /\/(.*)\//;
const str = `just/the/path/to/file.txt`;
let m;
if ((m = regex.exec(str)) !== null) {
console.log(m[1]);
}
This regex expression will do the trick
const str = "/the/path/to/the/peace";
console.log(str.replace(/[^\/]*\/(.*)\/[^\/]*/, "$1"));
[^\/]*\/(.*)\/[^\/]*
If you are interested in only matching consecutive parts with a single / and no //
^[^/]*\/((?:[^\/]+\/)*[^\/]+)\/[^\/]*$
^ Start of string
[^/]*\/ Negated character class, optionally match any char except / and then match the first /
( Capture group 1
(?:[^\/]+\/)* Optionally repeat matching 1+ times any char except / followed by matching the /
[^\/]+ Match 1+ times any char except /
) Close group 1
\/[^\/]* Match the last / followed by optionally matching any char except /
$ End of string
Regex demo
const regex = /^[^/]*\/((?:[^\/]+\/)*[^\/]+)\/[^\/]*$/;
[
"just/the/path/to/file.txt",
"just/the/path",
"/just/",
"just/the/path/to/",
"just/the//path/test",
"just//",
].forEach(str => {
const m = str.match(regex);
if (m) {
console.log(m[1])
};
});

Getting Multiple Matches with RegExp in JavaScript

I have a string like this:
`DateTime.now().setZone("America Blorp");`
This is my RegEx:
string.match(/DateTime\.(.*)[^)][(;]/)
How can I modify my RegEx so that I can get matches like this:
DateTime.now and DateTime.now.setZone.
I have tried to group matches like this
string.match(/DateTime\.(.*)([^)]*)([(;]*)/)
But I don't get the expected output. Can anyone please help me with this?
PS. I can only use match function, cannot use matchAll.
const string = `DateTime.now().setZone("America Blorp");`
console.log(
string.match(/DateTime\.(.*)[^)][(;]/)
)
You could match the format using 2 capture groups and concat the groups.
\b(DateTime\.now)\(\)(\.[^.()]+)\([^()]*\);
The pattern matches:
\b A word boundary to prevent a partial match
(DateTime\.now) Capture group 1, match DateTime.now
\(\) Match ()
(\.[^.()]+) Capture group 2, match . and 1+ times any char except . or ( and )
\([^()]*\); Match from ( till ) and ;
See a regex demo.
const regex = /\b(DateTime\.now)\(\)(\.[^.()]+)\([^()]*\);/;
const str = `DateTime.now().setZone("America Blorp");`;
const match = str.match(regex);
if (match) {
console.log(match[1] + match[2]);
}

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.

Extract a part of a regex name

Examples of filenames
FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
FDIP_fr-fr-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
FDIP_de-de-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
REGEX is FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
The only part I need is the translation code which is 'en-gb', 'fr-fr' , 'de-de.
How do I extract just that part of the filename?
Modified the regex little bit to match the numbers and text. You can play around here
Explanation
to capture a group you need to wrap the regex into () this will capture as a group.
to do the named capturing you can (?<name_of_group>) and then you can access by name.
Here goes the matching process.
[a-z]{2} match 2 char from a-z
[a-zA-Z0-9] match any char of a-z or A-Z or 0-9
g means global flag i.e. match all.
i means ignore case.
var r = /FDIP_([a-z]{2}-[A-Z]{2})-[a-z]{2}_Text_v1_[0-9A-Z]{8}_[A-Z0-9]{14}.txt/gi;
let t = 'FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt';
let dd = r.exec(t);
console.log(dd[1]);
This is example of group capturing
See the name in the regex and the object destructing name is matching.
const { groups: { language } } = /FDIP_(?<language>[a-z]{2}-[A-Z]{2})-[a-z]{2}_Text_v1_[0-9A-Z]{8}_[A-Z0-9]{14}.txt/gi.exec('FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt');
console.log(language);
To solve your problem, you should:
Fix your regex:
FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
// to
FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[0-9]{8}_[0-9]{14}.txt
Use get value from first group by using regex.exec function
const fileNames = [
'FDIP_en-gb-nn_Text_v1_20190101_12345678901234.txt',
'FDIP_fr-fr-nn_Text_v1_20200202_12345678901234.txt',
'FDIP_de-de-nn_Text_v1_20180808_12345678901234.txt']
const cultureNames = fileNames.map(name => {
const matched = /FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[0-9]{8}_[0-9]{14}.txt/.exec(name)
return matched && matched[1]
})
console.log(cultureNames)
Change FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
to
let pattern = /FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[\w]{8}_[\w]{14}.txt/;
var str = 'FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt';
console.log(str.match(pattern)[1]);

Extract all values matching a specific pattern

I have an input string
var input = 'J1,J2, J3';
I'm using the following pattern to extract the group value
var regex = /(,? ?(?<JOUR>J[0-9]+)+)/
while extracting the groups as below
var match = regex.exec(input);
match.groups contains only one group. How can i get all the groups J1 J2 and J3 from the input string ?
You can use .match of string to get groups
input.match(/J[0-9]+/g)
var input = 'J1,J2, J3';
console.log(input.match(/J[0-9]+/gi))
Match a capital J, then any amount of numbers:
var input = 'J1,J2, J3';
var regex = /J[0-9]+/g;
console.log(input.match(regex));
You could take the start of the string and the comma with an optional space into account and remove the outer group to use only 1 capturing group. To prevent the digits being part of a larger word you might add a word boundary \b
Note that you can omit the quantifier+ after )+ because that will repeat the group and will give you only the value of the last iteration.
(?:^|[,-] ?)(?<JOUR>J[0-9]+)\b
(?:^|[,-] ?) Match either the start of the string or comma or hyphen with an optional space
(?<JOUR>J[0-9]+) Named capture group JOUR, match J and then 1+ digits
\b Word boundary to prevent the digits being part of a larger word
Regex demo
Use exec to get the value from the first capturing group
const regex = /(?:^|, ?)(?<JOUR>J[0-9]+\b)+/g;
let m;
[
"J1, J2, J3 - J5, J7",
"J1,J2, J3"
].forEach(str => {
while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
console.log(m[1]);
}
});
const input = 'J1,J2, J3,J10';
const regexJfollowOneDigit = /(J\d{1}(?!\d))/g
const regexJfollowOneOrMoreDigit = /(J\d+)/g
console.log(input.match(regexJfollowOneDigit))
console.log(input.match(regexJfollowOneOrMoreDigit))

Categories