Regex with dynamic requirement - javascript

Suppose I have string:
var a = '/c/Slug-A/Slug-B/Slug-C'
I have 3 possibility:
var b = 'Slug-A' || 'Slug-B' || 'Slug-C'
My expectation:
if (b === 'Slug-A') return 'Slug B - Slug C';
if (b === 'Slug-B') return 'Slug A - Slug C';
if (b === 'Slug-C') return 'Slug A - Slug B';
What I've done so far:
a.replace(b,'')
.replace(/\/c\//,'') // clear /c/
.replace(/-/g,' ')
.replace(/\//g,' - ')
Then, I'm stuck
Any help would be appreciated. Thanks

Try this:
var a = '/c/Slug-A/Slug-B/Slug-C'
var b = 'Slug-A' || 'Slug-B' || 'Slug-C'
var reg = new RegExp(b.replace(/([A-z]$)/,function(val){return '[^'+val+']'}),'g');
a.match(reg).map(function(val){return val.replace('-',' ')}).join(' - ');
Explication:
the replacement of the string b catch the last latter of the string and replace it with the ^ regex sign. this mean that instead of capture it it will ignore it.
That mean that mean that now it will match only the Slag- that isn't contain the last char.
All there is to do is to return it with any join you like.

Try this, I made it as simple as possible.
var a = '/c/Slug-A/Slug-B/Slug-C';
var b = 'Slug-A';
var regex = new RegExp(b+'|\/c\/|-|\/','g');
alert(a.replace(regex, " ").trim().replace(/(\s.*?)\s+/,'$1 - '));
//OR
alert(a.replace(regex, " ").trim().match(/\w+\s\w/g).join(' - '));
Explanation
1) b+'|\/c\/|-|\/','g' = matches b value, /c/ , - and /
2) a.replace(regex, " ") = replace all the matched part by space. so a would beSlug A Slug B
3) .replace(/(\s.*?)\s+/,'$1 - ') = match two spaces with anything within the spaces. And then replace it with the match + ' - ' appended to it.
Note that we have grouped the part (\s.*?) in the regex (\s.*?)\s+. So this grouping is done so that It can be used while replacing it with a new text. $1 holds the grouped part of the matched text so $1 = " A". So what I am doing is I match the regex Eg : " A " and replace only the grouped part ie " A" with " A" + " - " = " A - ".
4) .match(/\w+\s\w/g).join(' - ') = match all the part where characters followed by a space followed by a character. match will return a array of matched parts. So then I join this array by using join.

Do it this way
var a = '/c/Slug-A/Slug-B/Slug-C'
var b = 'Slug-A'
//var b = 'Slug-B'
//var b = 'Slug-C'
var k = a.replace(b,'')
.replace(/\/c\//,'') // clear /c/
.replace(/-/g,' ')
.match(/[a-zA-Z -]+/g).join(" - ")
console.log(k)
working array here

Related

search and convert Uppercase to small case and inserting ''-'' in javascript

thanks in advance,
I have a string as "fileName = 'CampaignDetail'" .I want to make it 'campaign-detail'.That is converting all the upper case letters to small and insert hyphen wherever in between it is capital letter.how can I do it with for loop.
Check this approach using split and reduce
"CampaignDetail".split(/(?:([A-Z]))/).reduce( (a,b,i) => i == 1 || i % 2 == 0 ? a + b : a + "-" + b ).toLowerCase() //campaign-detail
Demo
function toHypenCase( input )
{
return input.split(/(?:([A-Z]))/).reduce( (a,b,i) => i == 1 || i % 2 == 0 ? a + b : a + "-" + b ).toLowerCase();
}
console.log( toHypenCase( "CampaignDetail" ) );
You can do it using regular expression. Try following
let regex = /[A-Z](\s\S)*[a-z]*/g;
let name = 'CampaignDetail';
let tempData = name.match(regex);
filename = tempData.reduce((a,b) => {
return a.toLowerCase() + '-' + b.toLowerCase();
})
console.log(filename);
Try it. Hope it helps
var string = "CampaignDetail";
string = string.replace(/([a-z])([A-Z])/g, '$1-$2');
string = string.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
alert(string.toLowerCase());
RegEx only solution:
"CampaignDetailKebabCase".replace(/(.)([A-Z]{1})/g, '$1-$2').toLowerCase();
Here we globally search for uppercase letter ([A-Z]) placed after any symbol (.) and replace this with the same any symbol '$1' , dash symbol '-' and the same upper case later '$2'.

Adding a whitespace in front of the first number in a string

I need a whitespace to be added in front of the first number of a string, unless there is one already and unless the number is the first character in the string.
So I wrote this JS code:
document.getElementById('billing:street1').addEventListener('blur', function() {
var value = document.getElementById('billing:street1').value;
var array = value.match(/\d{1,}/g);
if (array !== null) {
var number = array[0];
var index = value.indexOf(number);
if(index !== 0){
var street = value.substring(0, index);
var housenumber = value.substring(index);
if (street[street.length - 1] !== ' ') {
document.getElementById('billing:street1').value = street + ' ' + housenumber;
}
}
}
});
Fiddle
It works fine, but I feel like this can probably be done in a smarter, more compact way.
Also, JQuery suggestions welcome, I am just not very familiar with it.
Try this one :
const addSpace = (str) => {
return str.replace(/(\D)(\d)/, "$1 $2")
}
console.log(addSpace("12345")) // "12345"
console.log(addSpace("city12345")) // "city 12345"
console.log(addSpace("city")) // "city"
(\D) captures a non-digit
(\d) captures a digit
so (\D)(\d) means : non-digit followed by a digit
that we replace with "$1 $2" = captured1 + space + captured2
You can do it by using only regular expressions. For example:
var s = "abcde45";
if(!s.match(/\s\d/)){
s = s.replace(/(\d)/, ' $1');
}
console.log(s); // "abcde 45"
UPD : Of course, if you have string with a wrong syntax(e.g no numbers inside), that code wouldn't work.

Extract chars enclosed in complex brackets within a string in most efficient way

I have a string in which there are brackets, and in brackets could be another brackets. For example:
var string1 = "1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))";
Every open bracket is closed, but not necessarily immediately, meaning, inside a bracket could be another bracket. Chars, digits and other signs like + - # $ % (excluding '!") can be all over the string, grouped or solo.
What I want is to extract every char from brackets (regardless if it is numeral, letter, sign...), and format those chars separated with one blank space, including that if there are chars that go immediately one after another, like "c+" or "e-fg" in example, they would be grouped together. In above example, result would be:
var string2 = "C b c+ d e-fg h j k";
I have this code that does this:
var string1 = '1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))';
var opens = new Array();
opens.push(string1.indexOf('('));
string1 = string1.replace('(','!')
var closes = new Array();
var done = false;
while (!done) {
openindex = string1.indexOf('(');
closeindex = string1.indexOf(')');
string1 = string1.replace(')','!').replace('(','!');
if (openindex>closeindex) {
opens.push(openindex);
closes.push(closeindex);
}
if (string1.indexOf(')')==-1) {
closes.push(closeindex);
done = true;
}
}
var string2 = '';
for (var i=0;i<opens.length;i++) string2 = string2 + string1.substring(opens[i],closes[i]);
string2 = string2.replace(/!!/g,' ').replace(/!/g,' ').replace(/ /g,' ');
This works (https://jsfiddle.net/nL2gp80j/1/), but I am looking for more efficient solution. I don't know regex, and maybe this could be acomplished much better and faster with it.
There is a much shorter and better way to achieve desired result without involving regular expressions a lot more:
str = '1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))';
array = [], counter = 0;
str.split(/([()])/).filter(Boolean).forEach(function(e, i, a) {
// Increase / decrease counter and push desired values to an array
e == '(' ? counter++ : e == ')' ? counter-- : counter > 0 ? array.push(e) : true;
if (i === a.length - 1)
// Join all values with a whitespace between
console.log(array.join(' '));
});
Use a regex to extract the letters with grouping. Use String.prototype.match() method with a regular expression as an argument for this:
var str = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))";
var ex = str.match(/([a-z])+/g); // will give you grouped letters
console.log(ex.join(" ")); // and join it with a space.
Use this regex /[^a-z]*/ig it will replace everything other than char
var string1 = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))";
string1 = string1.match(/[a-z]+/ig);
string1=string1.join(" ");
console.log(string1);
[Edited from comment #Jai]
Use this, if ensured that the brackets are in the right adjustment.
var string1 = "1 2 (a(b(c d)efg)) 3 4 (h j) 5 6 ((k))";
string1 = string1.replace(/[\(\)]*/ig,'');
alert(string1);
Note: I edited the replace-string beacause there was a copy-paste error.
I don't see a simple way to do it in only one regex, but this does the job:
var string1 = "1 a (C(b(c+ d)e-fg)) 3# 4df (h j) 5 6 ((k))";
// remove before the first (
string1 = string1.replace(/^[^()]*\(/, '(');
// reome after the last )
string1 = string1.replace(/\)[^()]*$/g, ')');
// remove outside parenthesis
string1 = string1.replace(/\)[^()]+\(/g, ')(');
// while there is at least one (
while (string1.indexOf('(') != -1) {
// remove pair of parenthesis
string1 = string1.replace(/\(([^()]+)\)/g, " $1 ");
}
// remove superfluous spaces
string1 = string1.replace(/ +/g, ' ');
console.log(string1);

Backward capture group concatenated with forward capture group

I think the title says it all. I'm trying to get groups and concatenate them together.
I have this text:
GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48
And I want this output:
IDENTIFIER 10.802.123/3843-48
So I want to explicitly say, I want to capture one group before this word and after, then concatenate both, only using regex. Is this possible?
I can already extract the 48 like this:
var text = GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48
var reg = new RegExp('IDENTIFIER' + '.*?(\\d\\S*)', 'i');
var match = reg.exec(text);
Output:
48
Can it be done?
I'm offering 200 points.
You must precisely define the groups that you want to extract before and after the word. If you define the group before the word as four or more non-whitespace characters, and the group after the word as one or more non-whitespace characters, you can use the following regular expression.
var re = new RegExp('(\\S{4,})\\s+(?:\\S{1,3}\\s+)*?' + word + '.*?(\\S+)', 'i');
var groups = re.exec(text);
if (groups !== null) {
var result = groups[1] + groups[2];
}
Let me break down the regular expression. Note that we have to escape the backslashes because we're writing a regular expression inside a string.
(\\S{4,}) captures a group of four or more non-whitespace characters
\\s+ matches one or more whitespace characters
(?: indicates the start of a non-capturing group
\\S{1,3} matches one to three non-whitespace characters
\\s+ matches one or more whitespace characters
)*? makes the non-capturing group match zero or more times, as few times as possible
word matches whatever was in the variable word when the regular expression was compiled
.*? matches any character zero or more times, as few times as possible
(\\S+) captures one or more non-whitespace characters
the 'i' flag makes this a case-insensitive regular expression
Observe that our use of the ? modifier allows us to capture the nearest groups before and after the word.
You can match the regular expression globally in the text by adding the g flag. The snippet below demonstrates how to extract all matches.
function forward_and_backward(word, text) {
var re = new RegExp('(\\S{4,})\\s+(?:\\S{1,3}\\s+)*?' + word + '.*?(\\S+)', 'ig');
// Find all matches and make an array of results.
var results = [];
while (true) {
var groups = re.exec(text);
if (groups === null) {
return results;
}
var result = groups[1] + groups[2];
results.push(result);
}
}
var sampleText = " GPX 10.802.123/3843- 1 -- IDENTIFIER 48 A BC 444.2345.1.1/99x 28 - - Identifier 580 X Y Z 9.22.16.1043/73+ 0 *** identifier 6800";
results = forward_and_backward('IDENTIFIER', sampleText);
for (var i = 0; i < results.length; ++i) {
document.write('result ' + i + ': "' + results[i] + '"<br><br>');
}
body {
font-family: monospace;
}
You can do:
var text = 'GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48';
var match = /GPX\s+(.+?) \d .*?(IDENTIFIER).*?(\d\S*)/i.exec(text);
var output = match[2] + ' ' + match[1] + '-' + match[3];
//=> "IDENTIFIER 10.802.123/3843­-48"
This would be possible through replace function.
var s = 'GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48'
s.replace(/.*?(\S+)\s+\d+\s*-\s*(IDENTIFIER)\s*(\d+).*/, "$2 $1-$3")
^\s*\S+\s*\b(\d+(?:[./]\d+)+)\b.*?-.*?\b(\S+)\b\s*(\d+)\s*$
You can try this.Replace by $2 $1-$3.See demo.
https://regex101.com/r/sS2dM8/38
var re = /^\s*\S+\s*\b(\d+(?:[.\/]\d+)+)\b.*?-.*?\b(\S+)\b\s*(\d+)\s*$/gm;
var str = 'GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48';
var subst = '$2 $1-$3';
var result = str.replace(re, subst);
You can use split too:
var text = 'GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48';
var parts = text.split(/\s+/);
if (parts[4] == 'IDENTIFIER') {
var result = parts[4] + ' ' + parts[1] + '-' + parts[5];
console.log(result);
}

Regex to replace the last number in a filename

I'm creating functionality to increase the last number in a filename with 1.
Samples:
filename01.jpg => filename02.jpg
file01name01.jpg => file01name02.jpg
file01na01me.jpg => file01na02me.jpg
I'm struggling with the cases where the original file name contains the same number two or more times. I only want to increase the last number in the filename.
I have done some research, but not been able to find a correct regex. Perhaps someone could help me.
Ideally I want my code to look something like this:
var filename = "somefilename";
var newFilename = filename.replace(regex,lastNumber + 1);
I'm not sure if it could be done this easy. But I need to figure out the regex before I move on.
Thanks to pivmvb, here is my final solution:
function getIncreasedFileName(fileName){
var newFileName = fileName.replace(/(\D+)(\d+)(\D+)$/,
function(str, m1, m2, m3) {
var newstr = (+m2 + 1) + "";
return m1 + new Array(m2.length+1 - newstr.length).join("0") + newstr + m3;
})
return newFileName;
}
"test01.jpg".replace(/(\D+)(\d+)(\D+)$/, function(str, m1, m2, m3) {
var newstr = (+m2 + 1) + "";
return m1 + new Array(3 - newstr.length).join("0") + newstr + m3;
// m1 === "test"
//
// m2 === "01"
// So:
// +m2 + 1 === 2
//
// (+m2 + 1) + "" === "2"
// (convert to string, call this `newstr`)
//
// new Array(3 - newstr.length).join("0") === "0"
// (this adds an appropriate amount of leading zeroes
// so that the total length is 2)
//
// m3 === ".jpg"
});
Where:
\D+ one or more non-digits
\d+ one or more digits
\D+ one or more non-digits
$ end of string (so it only matches the last digits)
Then replace the matched string by a function that returns a new string, after doing the following:
adding 1 to the number
adding leading zeroes
Here's what I came up with:
var newFilename = filename.replace(/(\d+)(\D*$)/g ,
function(match, c1, c2) {
var nextNum = (+c1 + 1);
return (nextNum < 10 ? "0" + nextNum : nextNum) + c2;
});
Note that I used \D* to match zero or more non-digits between the last number and the end of the string, so that will change "filename.01" to "filename.02" and "name01" to "name02". If you only want to match where there are other characters after the number simply change the * to a + to match one or more non-digits at the end.
You can first find the last digits, increase them and then do the replace:
m = filename.match(/([0-9][0-9])([^0-9]*)$/);
incr = parseInt(m[1]) +1;
newFilename = filename.replace(/([0-9][0-9])([^0-9]*)$/, incr + "$2");
This doesn't add the padding 0 in case number is below zero. I'll let that to you.

Categories

Resources