Javascript regexp replace capturing - javascript

I'm trying to use regex in a Nodejs app. I usually use it in Python and it seems to have some differences.
Here is the problem :
I have this string \newcommand{\hello}{#replace} and I want to replace #replace by REPLACED in the second curly bracelets ONLY when I found \hello in the first curly bracelets. So the expected result is : \newcommand{\hello}{REPLACED}
I try this:
r = new RegExp('\\newcommand{\\hello}{(.*?)}');
s = '\\newcommand{\\hello}{#replace}';
s.replace(r, 'REPLACED');
But nothing is replaced... any clue?

r = new RegExp(/\\newcommand{\\hello}{#replace}/);
s = '\\newcommand{\\hello}{#replace}';
let a = s.replace(r, '\\newcommand{\\hello}{REPLACED}');
console.log(a)
Output would be : "\newcommand{\hello}{REPLACED}"

I'm not sure if I understood the question correctly. Is this what you're looking for?
function replaceWith(myReplacement) {
var original = "\\newcommand{\\hello}{#replace}";
var regex = "{\\hello}{#replace}";
return original.replace(regex, `{\\hello}{${myReplacement}}`)
};
console.log(replaceWith("World"));

You don't need regex at all to perform this kind of operation. You can simply use string at first parameter:
s = '\\newcommand{\\hello}{#replace}';
s.replace('#replace', 'REPLACED'); // => "\newcommand{\hello}{REPLACED}"

Related

Regex append characters to a substring

My string comes in two flavours-
var a = /aid/f82eb514073124cd10d468b74eee5663?sg=1#/propertyinfo
or
var a = /aid/f82eb514073124cd10d468b74eee5663#/propertyinfo
I want to append the content that comes after aid/ and before ? or # with "-test". In either of the above scenarios the result would be f82eb514073124cd10d468b74eee5663-test
hence
a = /aid/f82eb514073124cd10d468b74eee5663-test#/propertyinfo
or
a = = /aid/f82eb514073124cd10d468b74eee5663-test?sg=1#/propertyinfo
Seems like you're looking for something like this.
Regular expression /\/aid\/[0-9A-F]*/i and replacement expression $0-test.
JavaScript is a little bit different than just plain regular expression antics, so here you go;
var a = "/aid/f82eb514073124cd10d468b74eee5663?sg=1#/propertyinfo";
alert(a.replace(/(\/aid\/[0-9A-F]*)/i, "$1-test"));
given your examples I guess that string after /aid/ is some kind of md5 hash
this should work for you:
'/aid/f82eb514073124cd10d468b74eee5663#/propertyinfo'.replace(new RegExp('/aid/([a-f0-9]{32})'), '$1-test');
if you don't want to be that much specific about length, you can try the following:
'/aid/f82eb514073124cd10d468b74eee5663#/propertyinfo'.replace(new RegExp('/aid/([a-f0-9]+)'), '$1-test');
Simple solution using String.replace function:
var a = '/aid/f82eb514073124cd10d468b74eee5663sg=1#/propertyinfo',
result = a.replace(/aid\/([^?#]+)(?=\?|#)/, "aid/$1-test");
console.log(result); // /aid/f82eb514073124cd10d468b74eee5663-test?sg=1#/propertyinfo
I suggest replacing directly the # or ? so the regex is nice and simple. :)
var a = "/aid/f82eb514073124cd10d468b74eee5663?sg=1#/propertyinfo";
var b = "/aid/f82eb514073124cd10d468b74eee5663#/propertyinfo";
console.log(a.replace(/([\?#])/,"-test$1"));
console.log(b.replace(/([\?#])/,"-test$1"));
var a = '/aid/f82eb514073124cd10d468b74eee5663?sg=1#/propertyinfo';
a.replace(/(\/aid\/.+)(\?sg=1)(#\/propertyinfo)/,function(text,c,d,e){
return c+'-test'+e;
})
//Output: "/aid/f82eb514073124cd10d468b74eee5663-test#/propertyinfo"
a.replace(/(\/aid\/.+)(\?sg=1#\/propertyinfo)/,function(text,c,d){
return c+'-test'+d;
});
//Output: "/aid/f82eb514073124cd10d468b74eee5663-test?sg=1#/propertyinfo"

Regex: .exec() function not returning expected output

This doesn't return what I, or regex101, expects:
var myString = "Accel World|http://www.anime-planet.com/anime/accel-worldAh! My Goddess|http://www.anime-planet.com/anime/ah-my-goddess";
var reg = /[^|]*/g;
var regResponse = reg.exec(myString);
console.log(regResponse);
according to regex101, this should match everything except '|' and return it yet it only matches the first string, Accel World, as opposed to everything but '|'.
How do I fix this?
Exec will only return one result at a time (subsequent calls will return the rest, but you also need to use the + instead of *)
You could use the myString.match(reg) htough to get all results in one go.
var myString = "Accel World|http://www.anime-planet.com/anime/accel-worldAh! My Goddess|http://www.anime-planet.com/anime/ah-my-goddess";
var reg = /[^|]+/g;
var regResponse = myString.match(reg);
console.log(regResponse);
You need to loop .exec() to retrieve all matches. The documentation says
If your regular expression uses the "g" flag, you can use the exec()
method multiple times to find successive matches in the same string.
var reg = /[^|]+/g;
while(regResponse = reg.exec(myString)) {
console.log(regResponse);
}
Try a "+" instead of the "*"
So,
var reg = /[^|]+/g;

regex to find a string that comes after =

I´m really new to regex and I have been looking around to find an answer but either it dont work or I get some kind of error so I will try to ask the question and hopefulyl somebody can guide me through it :)
I have a string that can look like this:
str = "car[brand=saab][wheels=4]"
I have no idea if you can get several different matches directly or if you need different .match() but anyhow.
I need everything before the first [] in 1 variable.
Then i need saab in another, and 4 in a third.
.replace with a callback function is your tool of choice when parsing custom formats in javascript. Consider:
parse = function(s) {
var result = {};
s.replace(/^(\w+)|\[(.+?)=(.+?)\]/g, function($0, $1, $2, $3) {
result[$2 || "kind"] = $1 || $3;
});
return result;
}
Example:
str = "car[brand=saab][wheels=4][price=1234][morestuff=foobar]"
console.log(parse(str))
// {"kind":"car","brand":"saab","wheels":"4","price":"1234","morestuff":"foobar"}
You can use this regex:
([^\[]*)\[[^=]+=([^\]]*)\]\[[^=]+=([^\]]*)\]
You can then grap matching group #1, #2 and #3
Live Demo: http://www.rubular.com/r/XNZfHcMAp8
In Javascript:
str = 'car[brand=saab][wheels=4]';
console.log('match::' + str.match(/([^[]*)\[[^=]+=([^\]]*)\]\[[^=]+=([^\]]*)\]/));
I think this should work :
([^[]+)(?:\[[^=]+=([^\]]+)\])+
Explainations :
([^[]) First, you match everything that is not a [.
(?:...)+ Then, when you find it, you're starting repeting a pattern
\[[^=] Find everything that is not an =, and discard it.
([^\]]) Find everything that is not a ] and capture it.
/([^\[]+)\[brand=([^\]]+)\]\[wheels=(\d)\]/
Works.
Try it like
var result = "car[brand=saab][wheels=4]".match(/([^\[]+)\[brand=([^\]]+)\]\[wheels=(\d)\]/)
Result would be
[ "car[brand=saab][wheels=4]", "car", "saab", "4" ]
you could do it with match in one shot, and get an array back.
below lines were tested in chrome console:
str = "car[brand=saab][wheels=4]";
"car[brand=saab][wheels=4]"
str.match(/[^=[\]]+(?=[[\]])/g)
["car", "saab", "4"]
function getObject(str) {
var props = str.split(/\[(.*?)\]/g),
object = {};
if (props.length) {
object.name = props.shift();
while (props.length) {
var prop = props.shift().split("=");
if(prop.length == 2){
object[prop[0]] = prop[1];
}
}
}
return object;
}
console.log(getObject("car[brand=saab][wheels=4]"));

JavaScript indexOf to ignore Case

I am trying to find if an image has in its source name noPic which can be in upper or lower case.
var noPic = largeSrc.indexOf("nopic");
Should I write :
var noPic = largeSrc.toLowerCase().indexOf("nopic");
But this solution doesn't work...
You can use regex with a case-insensitive modifier - admittedly not necessarily as fast as indexOf.
var noPic = largeSrc.search(/nopic/i);
No, there is no case-insensitive way to call that function. Perhaps the reason your second example doesn't work is because you are missing a call to the text() function.
Try this:
var search = "nopic";
var noPic = largeSrc.text().toLowerCase().indexOf(search.toLowerCase());
Note that if the search string is from user input you'll need to escape the special regexp characters.
Here's what it would look like:
var search = getUserInput();
/* case-insensitive search takes around 2 times more than simple indexOf() */
var regex = RegExp(search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), "i");
var noPic = testString.search(regex);
See the updated jsperf: http://jsperf.com/regex-vs-tolowercase-then-regex/4
footnote: regexp escaping from https://stackoverflow.com/a/3561711/1333402
Try with:
var lowerCaseLargeSrc = largeSrc.toLowerCase();
var noPic = lowerCaseLargeSrc.indexOf("nopic");
Your code will only work if largeSrc is already a string. You might be getting an input that's an html element instead. So, use jQuery to resolve any potential input element into the text that's inside it. Example:
var noPic = largeSrc.text().toLowerCase().indexOf("nopic");
How about using findIndex instead that way you can do all your toLowerCase() inside the callback. Worked great for me:
// Not Supported in IE 6-11
const arr = ['HELLO', 'WORLD'];
const str = 'world';
const index = arr.findIndex(element => {
return element.toLowerCase() === str.toLowerCase();
});
console.log(index); // 👉️ 1
if (index !== -1) {
// 👉️ string is in the array
}
Credit:
https://bobbyhadz.com/blog/javascript-make-array-indexof-case-insensitive

RegExp to match words wrapped in braces

In javascript, I've got a block of HTML like this:
<h2>{title}</h2>
<p>{content}</p>
And I'm trying use regex "match" to spit out an array of all the {item}'s. So my output should look like:
['title', 'url', 'content']
I've gotten as far as:
var pattern = new RegExp("\{[a-zA-Z]+\}+");
var match = pattern.exec("{Sample} bob {text}");
But it's only returning the first tag.
This is just beyond my regex skills. Can anyone help?
Cheers!
You need to create a pattern with the global flag:
var pattern = new RegExp("\{[a-zA-Z]+\}", "g");
or:
var pattern = /\{[a-zA-Z]+\}/g;
Then you can call the match() method on your string to get a list of matches:
var matches = "{Sample} bob {text}".match(pattern);
I think you want:
var pattern = new RegExp("\{[a-zA-Z]+\}+", "g");
The second option is a flag telling it to search the entire string and return all matches.
See: http://www.evolt.org/article/Regular_Expressions_in_JavaScript/17/36435/ for more details.
Have you tried this yet?
<script>
var text = '<h2>{title}</h2>\n<p>{content}</p>';
var regex = /\{[a-z]+\}/ig;
var result = text.match(regex);
for (var i = 0; i < result.length; i++) {
console.debug(i + ". " + result[i]);
}
/*
gives:
0. {title}
1. {test}
2. {url}
3. {content}
*/
</script>
Much as I like to roll my own RegExp (and you really just need the global flag), have you looked at prototype templates, Trimpath JST or anything like that?
Because possibly rolling your own won't be as efficient for reuse as the above examples. EG:
String.prototype.template = function (obj) {
return this.replace(/{([^{}]+)}/g,
function (full, word) {
return((typeof obj[word]==='string'||typeof obj[word]==='number')?obj[word]:full);
}
);
};
"The {adj1} {adj2} {noun}.".template({adj1: 'lazy',adj2: 'brown', noun: 'dog'})
==> "The lazy brown dog."
This runs your regex each time, while I believe the prototype templates basically does it once.
I got off path by using exec for testing.

Categories

Resources