Regex matches in Javascript nesting issue - javascript

First of all, pardon my hacky code, I'm just trying to try this out and I'm learning javascript for the first time. Basically, Given the string "abc!random{3}" would mean return a string that starts with "abc" and ends with a random number from 0-3.
Here is what I have:
var pattern=/!random{([^{]*?)}/gi;
var text="abc!random{3}def!random{4}ghi!random{!random{3}}";
while (pattern.test(text))
{
text=text.replace(pattern, Math.random() * parseInt("$1"));
}
The problem is the parseInt function. It seems like the $1 does not get passed to it..the value of it gets cleared or something. If I do:
text=text.replace(pattern, "$1");
It correctly returns what is in between the { }, so the regex is working and the match is being stored in $1. However, as soon as I use it as a parameter to $1, it seems like the value of it is cleared. What gives?

The second parameter to replace can either be a string to replace the entire match, within which, if present, all occurances of $1, $2, etc. are replaced with the captures OR it can be a function that takes two parameters (the match and the capture) and returns a replacement string for the capture:
var pattern=/!random{([^{]*?)}/gi;
var text="abc!random{3}def!random{4}ghi!random{!random{3}}";
text=text.replace(pattern,
function(match,capture)
{
return Math.random() * parseInt(capture)
});
WScript.echo(text);
Notice that the while loop is unnecessary: the regular expression already has the global flag set ("g"), which says to process the regex globally.
Also note that the function actually receives multiple (m) arguments: 1=the matched string, 2..m=the captures from left to right, m+2=the offset within the string where the match occured, and m+3=the entire string being matched. JavaScript allows the right-most arguments (of any function) to be omitted, which is why the example has only two.

The replace method is operating on the value that it's passed. That is, if it gets a string containing $0, $1, etc., then it replaces that with the correct match. However, what you wrote is first parsing the string "$1" as an integer, multiplying it by a random number, and then passing that as the replacement. So it's almost certainly passing it NaN (due to being unable to parse "$1"), which is not what you want.
So, instead of
text = text.replace(pattern, Math.random() * parseInt("$1"));
I would try
var matches = text.match(pattern);
text = text.replace(pattern, Math.random() * parseInt(matches[1]));

Related

Replace a string fails in some cases

I must check a string and replace something of them.
I have to check if
$mystring='abc...';
has one of this values px,em,%,vh,s
I use this to check the string
function replaceUnit(input){ return input.replace(/(px|em|%|vh|s)/i ,'') }
It works but produces error in some cases.
If I have in my string for example
$mystring="its embeded"
The function will replace the "s" and "em" that's not the way it should be.
The function should check if in mystring is
only a number+px
or only a number+em
or only a number+%
or only a number+vh
or only a number+s
If there is a match, the function should replace the textpart, in all other cases the function should do nothing.
Is it possible to create a kind of this function and how a replace code must be?
Thanks a lot.
UPDATE
based on one of the answears i trie to change it
var input="0s";
function replaceUnit(input)
{
console.log('check: '+input);
var test=input.replace(/(\d)(?:px|em|%|vh|s)$/i ,'');
console.log('->: '+test);
return test
}
the result in the console is
check: 0s
->:
Add a $ (end-of-string anchor) to the end of the regular expression, to ensure that it'll only match if the characters occur at the very end, and capture a number before those characters, so that you can replace with that number alone (thus stripping out the extra characters):
return input.replace(/(\d)(?:px|em|%|vh|s)$/i ,'$1')
https://regex101.com/r/IodB6z/1

RegExp, JavaScript: Break string at specified characters, encode it, and insert it back in same position

I can't seem to find the correct JavaScript regular expression syntax to take a url string, get characters between other specified characters to encode, then insert back. My example may be easier to explain:
Example:
var url = 'http://www.myurl.com?t=23&dbUrl=http://www.encodeurl.com?t=23&otherUrl=http://www.anotherurl.com'
I need to grab the value between '&dbUrl=' and the next instance of 'http'. Take that value, 'encodeURIComponent' it, then insert it back into the var url to get:
http://www.myurl.com?t=23&dbUrl=http%3A%2F%2Fwww.encodeurl.com%3Ft%3D23%26otherUrl%3Dhttp://www.anotherurl.com
I tried splitting it at any instances of http and just encoding the [1]index of it but I don't always know when in the string '&dbUrl' will exist. I am not looking to break every query parameter but only alter the url between one query parameter and any instance of the next instance of 'http'. Only because the other query param, example used: '&otherUrl=' I wont know the exact query param so I wouldn't know when it stopped unless looking for the http. I will only know the query param of '&dbUrl='. Any ideas?
One approach would be to leverage the replace functionality to use a function as a second argument to return the transformed string. The return result of the function will end up as the replaced value in the original string,
url.replace(/(&dbUrl=)(.+)(?=http)/,
/*
m1 = first matched group
e.g, "&dbUrl=http://www.encodeurl.com?t=23&otherUrl="
m2 = second matched group
e.g, "&dbUrl="
m3 = third matched group
e.g, "http://www.encodeurl.com?t=23&otherUrl="
*/
function(m1, m2, m3) {
return m2 + encodeURIComponent(m3);
})
// returns,
// "http://www.myurl.com?t=23&dbUrl=http%3A%2F%2Fwww.encodeurl.com%3Ft%3D23%26otherUrl%3Dhttp://www.anotherurl.com"

Regex matching to exclude beginning word

How can I make the following JavaScript
'id=d41c14fb-1d42&'.match(/(?![id=])(.*)[^&]/)[0]
return "d41c14fb-1d42"? It currently returns "41c14fb-1d42", without the beginning "d".
This should do it:
'id=d41c14fb-1d42&'.match(/^id=(.*)&$/)[1]
// "d41c14fb-1d42"
~ edit
When an original question does not give any context it is hard to guess what you need exactly, in which case I just give a solution that yields the requested output. I now understand you want to be able to parse a query string, i.e., name1=value1&name2=value2.... The following regular expression yields nameX followed by an optional =valueX, as I believe it is valid to provide just the parameter in a query string without a value.
var parameters = "id=foobar&empty&p1=javascript&p2=so".match(/\w+(=([^&]+))?/g)
// ["id=foobar", "empty", "p1=javascript", "p2=so"]
You can split on "=" to obtain parameter and value separately.
var param1 = parameters[0].split("=")
// ["id", "foobar"]
For a parameter without the value that would just yield an Array with 1 value, of course.
"empty".split("=") // ["empty"]
Note this assumes a query parameter to match \w+, if there are other cases you have to expand the regular expression.
If you only want to match the id parameter specifically anywhere in the query string and obtain its value, as I infer from your comment below, you can use:
"id=donald".match(/(?:^|&)id=([^&]+)/)[1]
// "donald"
"param1=value1&id=donald&param2=value2".match(/(?:^|&)id=([^&]+)/)[1]
// "donald"

Javascript - remove repeating characters when there are more than 2 repeats

As what the title says. When there are more than 2 repeats of a letter in a string, the excess repeats are removed.
I have the following code based off this answer but it does not seem to work:
function removeRepeatingLetters (text) {
return text.replace('^(?!.*([A-Za-z0-9])\1{2})(?=.*[a-z])(?=.*\d)[A-Za-z0-9]+$', '');
}
But it does not seem to work for my test string:
"bookkeepers! are amaazing! loooooooool"
The output for the sample string should be:
"bookkeepers! are amaazing! lool"
What am I doing wrong?
Try
"bookkeepers! are amaazing! loooooooool".replace(/(.)\1{2,}/g, '$1$1')
// "bookkeepers! are amaazing! lool"
The RegExp /(.)\1{2,}/ matches any single character followed by the same character two or more times.
The flag g ensures you match all occurrences.
Then, you replace each occurrence with the repeated character duplicated.
Note that the simpler .replace(/(.)\1+/g, '$1$1') should work too, but a bit slower because it does unnecessary replacements.
Another way (Oriol's answer works just fine) to do this is with a callback function:
function removeRepeatingLetters (text) {
return text.replace(/(.)\1{2,}/g, function(match, p1) {
return p1 + p1;
});
}
This will:
match an instances of an individual character repeated at least one - (.)\1{2,}
then it will pass the match and the first substring into a callback function - function(match, p1)
then it will return the first matched substring, appended to itself, as the value to replace the overall match - return p1 + p1;
Because of the g at the end of the regex, it will do it with all instances that it finds of repeated characters.
The above code works with the test string that you provided (along with a couple of others that I tested with ;) ). As mentioned, Oriol's works, but figured I'd share another option, since it gives you a glimpse into how to use the callback for .replace().

Changing character between two strings

How can i change the character after "#overlay/" and before "/" after that first one?
var x = "www.foo.com/#overlay/2/";
x.replace(/#overlay\/([^]*)\//, "1"); // i'm expecting: www.foo.com/#overlay/1/
I'm using this code, but no success. I don't understand that much from regex.
I've searched some questions but without success.
I would not use a regular expression here. You can just use .split().
var url, newUrl, peices;
url = 'www.foo.com/#overlay/2/';
// Split the string apart by /
peices = url.split('/');
// Changing the 3 element in the array to 1, it was originally 2.
peices[2] = 1;
// Let's put it back together...
newUrl = peices.join('/');
You're making 3 mistakes :
you're replacing too much
you don't use the returned value. replace doesn't change the passed string (strings are immutable) but returns a new one
you forgot to precise in your capturing group when to stop (in fact it doesn't even have to be a capturing group)
You can do this :
x = x.replace(/(#overlay\/)[^\/]*\//, "$11/");
$1 here refers to the first captured group, so that you don't have to type it in the replacement string.
For example it changes
"www.foo.com/#overlay/2/rw/we/2345"
into
"www.foo.com/#overlay/1/rw/we/2345"

Categories

Resources