Below I'm trying to replace the moduleName string with another string replacementModule.
var replacementModule = 'lodash.string' // cheeky
var moduleName = 'underscore.string'
var pattern = new RegExp('^' + moduleName + '(.+)?')
var match = definition.match(pattern)
var outcome = replacementModule + match[1]
However right now a totally different module is matched as well.
underscore.string.f/utils // desired no change
underscore.string.f // desired no change
underscore.string // => lodash.string
underscore.string/utils // => lodash.string/utils
How can I match to the /, and how the outcome that I expect?
You need to do at least 3 things:
Escape the string variable passed to the RegExp
Check if match is null before using it
The regex should contain ($|/.*) as capturing group 1 to match either an end of string or / followed by 0 or more characters.
RegExp.escape = function(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};
function runRepl(definition, replacementModule, moduleName) {
var pattern = RegExp('^' + RegExp.escape(moduleName) + '($|/.*)');
// ^------------^ ^------^
var match = definition.match(pattern);
if (match !== null) { // Check if we have a match
var outcome = replacementModule + match[1];
document.write(outcome + "<br/>");
}
else {
document.write("N/A<br/>");
}
}
runRepl("underscore.string.f/utils", "lodash.string", "underscore.string");
runRepl("underscore.string.f", "lodash.string", "underscore.string");
runRepl("underscore.string", "lodash.string", "underscore.string");
runRepl("underscore.string/utils", "lodash.string", "underscore.string");
Escaping is necessary to match a literal . inside moduleName and ($|/)(.+)? presumes there can be something after an end of string. Also, (.+)? (1 or more characters) is actually the same as .* which is shorter and easier to read.
Related
I want to search and replace special characters of markdown (viz \`*_{}[]()#+.!|-) from the given string.
I am able to make it work in C# easily since there is verbatim # but Javascript not getting what's the issue. It seems something to do with /g , I read in another post which asked to use replaceAll but I could not find that method for string
C# version
string test = #"B
*H*
C
**AB**";
Console.WriteLine ("Input " + test);
var pattern = #"[\\`*_{}\[\]()#+-.!]";
var _1 = Regex.Replace (test, "\r?\n", "<br/>");
var out_ = Regex.Replace (_1, pattern, m => #"\" + m.Value);
Console.WriteLine ("Output " + out_);
Typescript Version
const regexM = new RegExp(/[\\\`\*\_\{\}\[\]\(\)#\+-\.!\|]/g, 'm');
var input = `B
*H*
C
**AB**`;
var inputString = input.replace(regexM, function (y: any) { return "\\" + y; });
if (/\r|\n/.exec(inputString))
{
inputString = inputString .replace(/\r?\n/g, "<br/>");
}
inputString = inputString.replace(regexM, function (x: any)
{
return "\\" + x;
});
Expected: B <br/>\*H\*<br/>C<br/>\*\*AB\*\*
I am getting B <br/>\*H*<br/>C<br/>**AB**
You may use
const regexM = /[\\`*_{}[\]()#+.!|-]/g;
var input = `B
*H*
C
**AB**`;
var inputString = input.replace(regexM, "\\$&");
inputString = inputString.replace(/\r?\n/g, "<br/>");
console.log(inputString);
// => B <br/>\*H\*<br/>C<br/>\*\*AB\*\*
NOTE:
The - in the regexM regex forms a range, you need to either escape it or - as in the code above - put it at the end of the character class
Rather than using callback methods, in order to reference the whole match, you may use the $& placeholder in a string replacement pattern
When you define the regex using a regex literal, there is only one backslash needed to form a regex escape, so const regexM = /[\\`*_{}[\]()#+.!|-]/g is equal to const regexM = new RegExp("[\\\\`*_{}[\\]()#+.!|-]", "g")
There is no need to check if there is a line break char or not with if (/\r|\n/.exec(inputString)), just run .replace.
This is my console.log:
str : +0-D : replace : Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
I have the following function:
function replaceAll_withMatching(str, find, rep, prodId) {
//console.log(str + " : " + find + " : " + rep + " : " + prodId);
var returnString = "";
if (find.toLowerCase() == str.toLowerCase()) {
returnString = rep;
} else {
escfind = "\\" + find ;
var regexp = new RegExp(escfind, "i");
var match = regexp.test(str);
if (match) {
var regAHREF = new RegExp("\\<a", "i");
var AHREFMatch = regAHREF.test(str);
if (AHREFMatch == false) {
str = str.replace(regexp, rep);
str = replaceProductAll(str, PRODUCT_PLACEHOLD, prodId);
} else {
var aTagText = $($.parseHTML(str)).filter('a').text();
if ((find !== aTagText) && (aTagText.indexOf(find) < 0)) {
console.log(regexp);
console.log("str : " + str + " : replace : " + str.replace(regexp, rep));
str = str.replace(regexp, rep);
}
}
}
//console.log(str);
returnString = str;
}
//returnString = replaceProductAll(returnString, PRODUCT_PLACEHOLD, prodId);
return returnString;
}
This function looks for a "<a>" tag, if it doesn't find one then it does the replace. If it does find one it has some conditions that if everything checks out it does another replace.
The string that I'm passing in has been already "parsed" on the +0:
+0-D
In the second pass I'm expecting it to find the "D" in the above string, and then do the following replacement:
D
But as you can see, after the 2nd replace it is jumbling the string and producing malformed HTML
Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
More Context:
I have a string that needs to have a replace done on it. This is existing code so I'm not in a position to rework the function.
The original string is: +0-D
This string gets passed into the function below multiple times looking for matches and then if it finds a match it will replace it with the value (also passed in as a parameter).
When the +0-D gets passed in the first time the +0 is matched and a replace is done: +0
Then the next time the string is passed in: +0-D. The function finds the D as a match and it looks like it attempts to do a replace. But it is on this pass that the string gets jumbled.
Ultimately what I'm expecting is this:
+0-D
This is what I'm currently getting after the 2nd attempt:
Da href="Javascript:PostRating('','|P|622','+0')">+0</a>-D
Further Context:
The +0-D is one of many strings this function handles. Some are very simple (i.e. Just +0), others are much more complex.
Question:
Based on the above, what do I need to do to get the regex to not jumble the string?
The problem was in the escfind:
escfind = "\\" + find;
var regexp = new RegExp(escfind,"i");
var match = regexp.test(str);
The first thing I did was in the 2nd replace clause I created a new RegExp to not use the "\\" + find;
if((find !== aTagText) && (aTagText.indexOf(find) < 0)){
try{
var regexp2 = new RegExp(find,"i");
var match2 = regexp2.test(str);
console.log(str.replace(regexp2,rep));
}catch(err){
console.log(err);
}
}
Then my string began to return as expected, however, when I opened it up to all the variations I was getting the Unexpected quantifier error.
Then I found this question - which lead me to escape out my find:
Once I replaced my code with this:
escfind = find.replace(/([*+.?|\\\[\]{}()])/g, '\\$1');
Then I got the output as expected:
<a href='+0'>+0</a>-<a href='D'>D</a>
Assume there is a string "aaaa/{helloworld}/dddd/{good}/ccc",
I want to get an array which contains the variables "helloworld" and "good" which are in braces {}.
Is there a simple way to implement this using regex?
Below function doesn't work:
function parseVar(str) {
var re = /\{.*\}/; // new RegExp('{[.*]}');// /{.*}/;
var m = str.match(re);
console.log(m)
if (m != null) {
console.log((m));
console.log(JSON.stringify(m));
}
}
parseVar("aaaa/{helloworld}/dddd/{good}/ccc");
The global flag (g) allow the regex to find more than one match. .* is greedy, meaning it will take up as many characters as possible but you don't want that so you have to use ? which makes it take up as little characters as possible. It is helpful to use regex101 to test regular expressions.
function parseVar(str) {
var re = /\{(.*?)\}/g;
var results = []
var match = re.exec(str);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
results.push(match[1])
match = re.exec(str);
}
return results
}
var r = parseVar("aaaa/{helloworld}/dddd/{good}/ccc")
document.write(JSON.stringify(r))
How can I match following patterns using JavaScript programming language?
sample (not sample in sampleword)
sam\nple
sa\nmple
I used \b for boundaries for full word match.
I'm trying to find an efficient way to do newline match anywhere in the word.
For case 2: \bsam[\s\S]ple\b works.
The same can be adapted for case3 as well to match.
But, Is there a way to have single pattern match all of those ?
It looks like you're asking how to match a string with a single optional space anywhere in the string? If so, that looks like this:
function getRegEx(word) {
var patterns = word.split('').map(function (letter, index) {
return (
word.slice(0, index) +
'\\s?' +
word.slice(index)
)
})
patterns.shift()
return new RegExp('^' + patterns.join('|') + '$');
}
getRegEx('pattern').test('pat tern') // --> true
However, if there can be multiple spaces in the string (as in 's amp le'), then it would be as follows:
function getRegEx(word) {
word = word.split('')
word = word.map(function (letter) {
return letter + '\\s?'
})
return new RegExp('^' + word.join('') + '$')
}
getRegEx('pattern').test('pat tern') // --> true
Per OP's request (see comments):
If you want to look for an indefinite number of space characters, pass true to the following function (as the second param). Otherwise, it'll just find one:
function getRegEx(word, mult) {
var spaceCount = mult ? '*' : '?'
word = word.split('')
word = word.map(function (letter) {
return letter + '\\s' + spaceCount
})
return new RegExp('^' + word.join('') + '$')
}
getRegEx('pattern', true).test('pat tern') // --> true
If you wish to specify where in the pattern spaces may appear, that can be done as follows:
function getRegEx(word, mult) {
word = word.split('')
var spaceCount = mult ? '*' : '?'
var positions = []
word.forEach(function (char, index) {
if (char === ' ') positions.push(index)
})
positions.forEach(function (pos) {
word.splice(pos, 1, '\\s' + spaceCount)
})
return new RegExp('^' + word.join('') + '$')
}
Put a space in your pattern string wherever you want there to be spaces matched. As in:
getRegEx('p at tern', true).test('p at tern') // --> true
You can remove \n using replace and compare that to sample using word boundaries:
/\bsample\b/i.test('sa\nmple'.replace(/\n/g, ''))
true
/\bsample\b/i.test('sam\nple'.replace(/\n/g, ''))
true
/\bsample\b/i.test('sample'.replace(/\n/g, ''))
true
/\bsample\b/i.test('sample'.replace(/\n/g, ''))
true
/\bsample\b/i.test('some sam\nple'.replace(/\n/g, ''))
true
\bsample\b/i.test('sam\nples'.replace(/\n/g, ''))
false
I have some difficulties with javascript. I'm currently working out a pagination skipper.
function skip(s)
{
var url = window.location.toString();
if(location.href.match(/(\?|&)currentpage=x($|&|=)/))
{
url=url.replace('currentpage=x','currentpage='+s);
window.location=url;
}
else
{
var newUrl = url+"¤tpage="+s;
window.location=newUrl;
}
}
I would like x to match any integer, so the entire string will be replaced.
Thanks!
The regex you're looking is this:
/((\?|&)currentpage=)\d+/
It matches and captures ?|¤tpage=, and matches the number that follows, but does not capture them. You can then replace the entire match with a string of your choice:
var newUrl = location.href.replace(/([?&]currentpage=)\d+/, '$1'+s);
Assuming that s here is the value for currentpage you want to replace the x in your example with. I've replaced the (\?|&) with a character class: [?&]. It simply matches a single character that is either a ? or an &. In the replacement string I back-reference the matched group ([?&]currentpage=), using $1, and concatenate s to it. It's as simple as that. To redirect:
location.href = location.href.replace(
/([?&]currentpage=)\d+/,
'$1' + s
);
And you're home free. Try it out in your console, like so:
'http://www.example.com/page?param1=value1¤tpage=123¶m2=foobar'.replace(
/([?&]currentpage=)\d+/,
'$1124'//replaced + s with 124
);
//output:
//"http://www.example.com/page?param1=value1¤tpage=124¶m2=foobar"
You can use following code,
function addParameter(url, param, value) {
// Using a positive lookahead (?=\=) to find the
// given parameter, preceded by a ? or &, and followed
// by a = with a value after than (using a non-greedy selector)
// and then followed by a & or the end of the string
var val = new RegExp('(\\?|\\&)' + param + '=.*?(?=(&|$))', 'i'),
qstring = /\?.+$/;
// Check if the parameter exists
if (val.test(url)) {
// if it does, replace it, using the captured group
// to determine & or ? at the beginning
return url.replace(val, '$1' + param + '=' + value);
}
else if (qstring.test(url)) {
// otherwise, if there is a query string at all
// add the param to the end of it
return url + '&' + param + '=' + value;
}
else {
// if there's no query string, add one
return url + '?' + param + '=' + value;
}
}
Usage,
function skip(s) {
window.location = addParameter(location.href, "currentpage", s);
}
Demo