Javascript regex replace yields unexpected result - javascript

I have this strange issue, hope that someone will explain what is going on.
My intention is to capture the textual part (a-z, hyphen, underscore) and append the numeric values of id and v to it, underscore separated.
My code:
var str_1 = 'foo1_2';
var str_2 = 'foo-bar1_2';
var str_3 = 'foo_baz1_2';
var id = 3;
var v = 2;
str_1 = str_1.replace(/([a-z_-]+)\d+/,'$1' + id + '_' + v);
str_2 = str_2.replace(/([a-z_-]+)\d+/,'$1' + id + '_' + v);
str_3 = str_3.replace(/([a-z_-]+)\d+/,'$1' + id + '_' + v);
$('#test').html(str_1 + '<br>' + str_2 + '<br>' + str_3 + '<br>');
Expected result:
foo3_2
foo-bar3_2
foo_baz3_2
Actual Result:
foo3_2_2
foo-bar3_2_2
foo_baz3_2_2
Any ideas?
JS Fiddle example

Your pattern:
/([a-z_-]+)\d+/
matches only "foo1" in "foo1_2", and "foo" will be the value of the captured group. The .replace() function replaces the portion of the source string that was actually matched, leaving the remainder alone. Thus "foo1" is replaced by "foo3_2", but the original trailing "_2" is still there as well.
If you want to alter the entire string, then your regular expression will have to account for everything in the source strings.

Just try with:
str_1 = str_1.match(/([a-z_-]+)\d+/)[1] + id + '_' + v;

Use this instead to capture 1_2 completely:
str_1 = str_1.replace(/([a-z_-]+)\d+_\d+/,'$1' + id + '_' + v);

Because you want to replace _2 also of string. Solution can be this:
str_1 = str_1.replace(/([a-z_-]+)\d+_\d/,'$1' + id + '_' + v);
str_2 = str_2.replace(/([a-z_-]+)\d+_\d/,'$1' + id + '_' + v);
str_3 = str_3.replace(/([a-z_-]+)\d+_\d/,'$1' + id + '_' + v);
DEMO

Your pattern actually includes the first digits, but it will store only the textual part into $1:
foo1_2
([a-z_-]+)\d+ = foo1
$1 = foo
The pattern stops searching at the first digits of the string.
if you want to replace any characters after the textual part, you could use this pattern:
/([a-z_-]+)\d+.*/

Related

javascript regex match between two strings and count the number of characters inside

I'm very new to js and programming, and i'd appreciate some help.
Suppose I have the following array (It is a single element array, they are not seperate elements)
var array =
[
'Foo\n' +
'bar23123\n' +
'barbarfoo\n' +
'foo, bar foo\n' +
'foo\n' +
'\n' +
'\n' +
'Bar\n' +
'\n' +
'\n'
]
Assuming there are multiple elements in the array, how can I write a regex expression to count and match the number of literal '\n' in between Foo\n and Bar\n in each element.
I wrote a partial solution to iterate through and return the count of all \n but how do I narrow my search to only return the values in between the two strings?
Here is the code:
let slashN = [];
for(let slash of array){
var reg = RegExp('\\n' , 'g')
slashN.push(slash.match(reg).length)
}
console.log(slashN);
I get the correct count, but I want to refine the regex expression.
Any help is highly appreciated.
You may use
var reg = /(?<=Foo\n.*?)\n(?=.*?Bar\n)/gs;
See the regex demo. Details:
(?<=Foo\n.*?) - a positive lookbehind that matches a location that is immediately preceded with Foo + newline and then any 0 or more chars, as few as possible
\n - a newline
(?=.*?Bar\n) - a positive lookahead that matches a location immediately followed with any 0+ chars as few as possible and then Bar + newline.
JavaScript demo:
var array =
[
'Foo\n' +
'bar23123\n' +
'barbarfoo\n' +
'foo, bar foo\n' +
'foo\n' +
'\n' +
'\n' +
'Bar\n' +
'\n' +
'\n'
];
let slashN = [];
for(let slash of array){
var reg = /(?<=Foo\n.*?)\n(?=.*?Bar\n)/gs;
slashN.push(slash.match(reg).length)
}
console.log(slashN);

Dynamically change element name in jquery

The following is my element id and I want to update it dynamically.
invoice[46][ap_details][4][ap_header_id]
I want to update only second number, i.e. [4], like this:
invoice[46][ap_details][5][ap_header_id]
I am using below code which is updating both the values.
var strNewName = $(this).attr('name').replace(/\[\d+\]/g, function(strName) {
strName = strName.replace(/[\[\]']+/g, '');
var intNumber = parseInt(strName) + 1;
return '[' + intNumber + ']';
});
Any help would be appreciated.
var strName = "invoice[46][ap_details][4][ap_header_id]";
var parts = strName.split('[');
parts[3] = parts[3].replace(/^\d+/, n => +n + 1);
var strNewName = parts.join('[');
console.log(strNewName);
If you don't want to use arrow functions replace this line:
parts[3] = parts[3].replace(/^\d+/, n => +n + 1);
with this:
parts[3] = parts[3].replace(/^\d+/, function(n) { return +n + 1; });
Explanation:
split will return an array like this:
[
"invoice",
"46]", // parts[1] to change this
"ap_details]",
"4]", // parts[3] to change this (and so on, you do the math)
"ap_header_id]"
]
The /^\d+/ will match any number at the begining (no need for the g modifier).
Replace with +n + 1 not n + 1 because n is a string, you have to force the interpretter to use it as a number or otherwise this "4" + 1 will result to this "41".
Then after you change what you want, join the parts using join with the same character you used for splitting ([).
Using this regex /((\w)+)(\[\d+\])(\[(\w)+\])(\[\d+\])(\[(\w)+\])/gi you can construct the string back and change your integer.
var match = /((\w)+)(\[\d+\])(\[(\w)+\])(\[\d+\])(\[(\w)+\])/gi.exec(youString);
//group 6 is your digit.
var newId = parseInt(match[6].replace("\[\]", "")) + 1;
var newString = match[1] + match[3] + match[4] + "[" + newId + "]" + match[7];
Here is a fiddle with the answer https://jsfiddle.net/gzfud9vc/
Maybe dont use regex to build your element id. You can do its as follows as well:
var id = 5
var name = "invoice[46][ap_details][";
name += id;
name += "][ap_header_id]";
var toReplace = "invoice[46][ap_details][~~id~~][ap_header_id]"
var replaced = toReplace.replace(/~~id~~/g, id);
console.log(name);
console.log(replaced);

Replacing all occurences in a string in javascript issue

This is my js code:
html = html.replace("/["+increment+"]/gi", '[' + counter + ']');
where increment is 0 and counter is 1
or
html = html.replace("/[0]/gi", '[1]');
My version does not replace the [0] with [1] in my string. Why ?
You need to use the RegExp constructor as the regex is dynamic
var regex = new RegExp("\\[" + increment + "\\]", 'gi')
html = html.replace(regex, '[' + counter + ']');
Also you could sanitize the dynamic variable if you want
if (!RegExp.escape) {
//A escape function to sanitize special characters in the regex
RegExp.escape = function (value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
//You could also escape the dynamic value it is an user input
var regex = new RegExp("\\[" + RegExp.escape(increment) + "\\]", 'gi')
html = html.replace(regex, '[' + counter + ']');
Use this way:
html = html.replace(new RegExp("\\["+increment+"\\]", "gi"), '[' + counter + ']');
This makes use of the dynamic values.

Changing a string that contains numbers into a number then back into a string

I know this sounds a bit silly, but I need to find a way to change a querystrings value without any hardcoding.
So for example:
post_num=_443_1
I want to change it to the following:
post_num=_444_1
I've already gotten post_num's value, I just need to be able to change it. Any ideas?
It really depends on the consistency of your format.
var numParts = str.split('_');
numParts[1]++;
var updated = '_' + numParts[1] + '_' + numParts[2];
Generic way to increment the first number in a string:
post_num.replace(/\d+/, function(n){return Number(n) + 1});
post_num.replace(/^_(\d+)_(\d)$/, function(match, value, sufix)
{
return "_" + (parseInt(value) + 1) + "_" + sufix;
});
or almost the same:
post_num.replace(/^_(\d+)_(\d)$/, function(match, value, sufix)
{
return "_" + (+value + 1) + "_" + sufix;
});

Javascript regexp: Using variables in backreference pattern?

I've got a pattern to find matches in a querystring:
'url.com/foo/bar?this=that&thing=another'.replace(/(thing=)([^&]*)/, '$1test')
What I'd like to be able to do is use variable values as the param to match like:
'url.com/foo/bar?this=that&thing=another'.replace('/(' + key + '=)([^&]*)/', '$1test')
[edit] Here's the context in how the code is being used:
GetSrcParam: function(key, value) {
var newSrc = $(this._image).attr('src'),
pattern = '(' + key + '=)([^&]*)';
if (newSrc.match(pattern) == null)
newSrc += '&' + key + '=' + value;
else
newSrc = newSrc.replace(newSrc, '$1' + value);
return newSrc;
}
But it's not working as intended - can anyone help?
If you choose to construct a regex from a string, you need to drop the delimiters (but then you need to double any backslashes, if your regex were to contain any). Try
myregex = new RegExp('(' + key + '=)([^&]*)')
'url.com/foo/bar?this=that&thing=another'.replace(myregex, '$1test')
Are you aware that this would also match thing=another in url.com/foo/bar?something=another? To avoid this, add a word boundary anchor:
myregex = new RegExp('(\\b' + key + '=)([^&]*)')

Categories

Resources