reg expression created from variable not working in .replace() - javascript

I'm doing a coding challenge that wants us to create a function that finds and replaces a word in a sentence. I define the reg expression like this
//"before" is the parameter with the word to be replaced
var regRep = '/'+before+'/gi';
and I'm using it like this
//"str" is the sentence to search and prepAfter" is a variable with the replacement word.
var newStr = str.replace(regRep, prepAfter);
when returning newStr I get the original str without any modifications. I went through and console.log()ed each of my variables and chunks of logic and the replace() method is the only thing not working as it's suppose to. Here's the entire function.
function myReplace(str, before, after) {
var prepAfter = "";
var caseCheck = before.charAt(0);
var regRep = '/'+before+'/gi';
if(caseCheck === caseCheck.toUpperCase()){
var firstLetter = after.substr(0,1).toUpperCase();
var wordLength = after.length -1;
var remWord = after.substr(1,wordLength);
prepAfter = firstLetter.concat(remWord);
}
else{ prepAfter = after; }
var newStr = str.replace(regRep, prepAfter);
return newStr;
}
What am I missing?

var regRep = new RegExp(before, 'gi');
If you pass a string to replace() (as you did), it will look for the actual string.
Note: if before is just a word in your case, you might not even need a regex, just passing it to replace() as-is could do. Depends on whether or not you need to check things like whitespace before and after.

Related

JS What's the fastest way to display one specific line of a list?

In my Javascript code, I get one very long line as a string.
This one line only has around 65'000 letters. Example:
config=123&url=http://localhost/example&path_of_code=blablaba&link=kjslfdjs...
What I have to do is replace all & with an break (\n) first and then pick only the line which starts with "path_of_code=". This line I have to write in a variable.
The part with replace & with an break (\n) I already get it, but the second task I didn't.
var obj = document.getElementById('div_content');
var contentJS= obj.value;
var splittedResult;
splittedResult = contentJS.replace(/&/g, '\n');
What is the fastest way to do it? Please note, the list is usually very long.
It sounds like you want to extract the text after &path_of_code= up until either the end of the string or the next &. That's easily done with a regular expression using a capture group, then using the value of that capture group:
var rex = /&path_of_code=([^&]+)/;
var match = rex.exec(theString);
if (match) {
var text = match[1];
}
Live Example:
var theString = "config=123&url=http://localhost/example&path_of_code=blablaba&link=kjslfdjs...";
var rex = /&path_of_code=([^&]+)/;
var match = rex.exec(theString);
if (match) {
var text = match[1];
console.log(text);
}
Use combination of String.indexOf() and String.substr()
var contentJS= "123&url=http://localhost/example&path_of_code=blablaba&link=kjslfdjs...";
var index = contentJS.indexOf("&path_of_code"),
substr = contentJS.substr(index+1),
res = substr.substr(0, substr.indexOf("&"));
console.log(res)
but the second task I didn't.
You can use filter() and startsWith()
splittedResult = splittedResult.filter(i => i.startsWith('path_of_code='));

Using Variable in Regex Character Set

i'm trying to use a variable (save) as a regex character set but keep getting null
function mutation(arr) {
var save = arr[1];
var rgx = /[save]/gi;
return arr[0].match(rgx).join('') == arr[0];
}
mutation(["Mary", "Army"]);
Goal of the function is to see if all the letters of arr[1] are contained in arr[0] by returning true or false. Function does work as i want it to when i manually put arr[1] into the character set (returns true in this situation), just cant get it to work with the variable.
Your exact current approach won't work (I think) due to it not being possible to build a regex pattern using /.../ notation with a variable. But, we can still use RegExp to build the pattern. For the sample data you showed us, here is a regex pattern which would work:
^(?!.*[^Mary]).*$`
In other words, we can assert, on the second string Army, that all its characters can be found in the first string Mary.
function mutation(arr) {
var save = arr[1];
var rgx = "^(?!.*[^" + save + "]).*$";
var re = new RegExp(rgx, "gi");
return re.test(arr[0]);
}
console.log(mutation(["Mary", "Army"]));
console.log(mutation(["Jon Skeet", "Tim Biegeleisen"]));

Javascript RegExp.prototype.test - how to regex values coming from an array

I want to check each values from my array if it matches the string,
however it doesn't work when i'm using console.log(/^reg_arr[i]/.test(str1));
but when I use console.log(/^table/.test(str1)); it works
var str1 = 'table football';
var reg_arr = ["table","football"];
for(var i = 0, reg_arr_length = reg_arr.length; i < reg_arr_length; i++)
{
console.log(/^reg_arr[i]/.test(str1)); /* doesnt work */
}
console.log(/^table/.test(str1)); /* this works */
Is there a problem with my syntax,
Thank you,
Use new RegExp(source: string[, flags: string]) (simply RegExp(source: string[, flags: string]) is also working)
var str1 = 'table football';
var reg_arr = ["table","football"];
for(var i = 0, reg_arr_length = reg_arr.length; i < reg_arr_length; i++)
{
console.log(new RegExp(`^${reg_arr[i]}`).test(str1));
}
Using slashes to define a regular expression doesn't allow you to enter variables into the regular expression, that is, in the following example, str1 is checked to contain "test", not the value of the variable test.
var str1 = "hello";
var str2 = "Hello world";
console.log(/str1/i.test(str2))
To solve this issue, you need to create a new regular expression for each value in the array, something that can be done with new RegExp(str), instead of slashes.
var str1 = "hello";
var str2 = "hello world";
console.log(new RegExp(str1, "i").test(str2))
However, this method has a catch, characters from that string are not escaped. So new RegExp("test.hello") will match "test hello", because the dot is interpreted as a regular expression wildcard character and not a period. To fix that, we first have to manually escape any special characters in our search string (unless the things reg_arr are actually regular expressions). I took the code to do that from the middle of this MDN page.
var str1 = "hello"
var str2 = "hello world"
str1.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
console.log(new RegExp(str, "i").test(str2))
So without changing anything else, your final console.log could look like this:
console.log(new RegExp(reg_arr[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).test(str1));

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;

Javascript: highlight substring keeping original case but searching in case insensitive mode

I'm trying to write a "suggestion search box" and I cannot find a solution that allows to highlight a substring with javascript keeping the original case.
For example if I search for "ca" I search server side in a case insensitive mode and I have the following results:
Calculator
calendar
ESCAPE
I would like to view the search string in all the previous words, so the result should be:
Calculator
calendar
ESCAPE
I tried with the following code:
var reg = new RegExp(querystr, 'gi');
var final_str = 'foo ' + result.replace(reg, '<b>'+querystr+'</b>');
$('#'+id).html(final_str);
But obviously in this way I loose the original case!
Is there a way to solve this problem?
Use a function for the second argument for .replace() that returns the actual matched string with the concatenated tags.
Try it out: http://jsfiddle.net/4sGLL/
reg = new RegExp(querystr, 'gi');
// The str parameter references the matched string
// --------------------------------------v
final_str = 'foo ' + result.replace(reg, function(str) {return '<b>'+str+'</b>'});
$('#' + id).html(final_str);​
JSFiddle Example with Input: https://jsfiddle.net/pawmbude/
ES6 version
const highlight = (needle, haystack) =>
haystack.replace(
new RegExp(needle, 'gi'),
(str) => `<strong>${str}</strong>`
);
nice results with
function str_highlight_text(string, str_to_highlight){
var reg = new RegExp(str_to_highlight, 'gi');
return string.replace(reg, function(str) {return '<span style="background-color:#ffbf00;color:#fff;"><b>'+str+'</b></span>'});
}
and easier to remember...
thx to user113716: https://stackoverflow.com/a/3294644/2065594
While the other answers so far seem simple, they can't be really used in many real world cases as they don't handle proper text HTML escaping and RegExp escaping. If you want to highlight every possible snippet, while escaping the text properly, a function like that would return all elements you should add to your suggestions box:
function highlightLabel(label, term) {
if (!term) return [ document.createTextNode(label) ]
const regex = new RegExp(term.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi')
const result = []
let left, match, right = label
while (match = right.match(regex)) {
const m = match[0], hl = document.createElement('b'), i = match.index
hl.innerText = m
left = right.slice(0, i)
right = right.slice(i + m.length)
result.push(document.createTextNode(left), hl)
if (!right.length) return result
}
result.push(document.createTextNode(right))
return result
}
string.replace fails in the general case. If you use .innerHTML, replace can replace matches in tags (like a tags). If you use .innerText or .textContent, it will remove any tags there were previously in the html. More than that, in both cases it damages your html if you want to remove the highlighting.
The true answer is mark.js (https://markjs.io/). I just found this - it is what I have been searching for for such a long time. It does just what you want it to.
I do the exact same thing.
You need to make a copy.
I store in the db a copy of the real string, in all lower case.
Then I search using a lower case version of the query string or do a case insensitive regexp.
Then use the resulting found start index in the main string, plus the length of the query string, to highlight the query string within the result.
You can not use the query string in the result since its case is not determinate. You need to highlight a portion of the original string.
.match() performs case insensitive matching and returns an array of the matches with case intact.
var matches = str.match(queryString),
startHere = 0,
nextMatch,
resultStr ='',
qLength = queryString.length;
for (var match in matches) {
nextMatch = str.substr(startHere).indexOf(match);
resultStr = resultStr + str.substr(startHere, nextMatch) + '<b>' + match + '</b>';
startHere = nextMatch + qLength;
}
I have found a easiest way to achieve it. JavaScript regular expression remembers the string it matched. This feature can be used here.
I have modified the code a bit.
reg = new RegExp("("+querystr.trim()+")", 'gi');
final_str = 'foo ' + result.replace(reg, "<b>&1</b>");
$('#'+id).html(final_str);
Highlight search term and anchoring to first occurence - Start
function highlightSearchText(searchText) {
var innerHTML = document.documentElement.innerHTML;
var replaceString = '<mark>'+searchText+'</mark>';
var newInnerHtml = this.replaceAll(innerHTML, searchText, replaceString);
document.documentElement.innerHTML = newInnerHtml;
var elmnt = document.documentElement.getElementsByTagName('mark')[0]
elmnt.scrollIntoView();
}
function replaceAll(str, querystr, replace) {
var reg = new RegExp(querystr, 'gi');
var final_str = str.replace(reg, function(str) {return '<mark>'+str+'</mark>'});
return final_str
}
Highlight search term and anchoring to first occurence - End

Categories

Resources