Replacing words in text that match regex - javascript

I am trying to replace all words in my text that match a give regex. I have made a function that looks like this:
const str = this.node.body;
const regex = /(href=\')([^\']*)(\')/g;
let newStr;
if (str.match(regex)) {
for(let i = 0; i < str.match(regex).length; i++) {
let url = str.match(regex)[i] + ' target="_blank"';
newStr = str.replace(str.match(regex)[i], url);
}
}
But, this is not right, since only the last value of the matching string will be replaced in the newStr, since in the loop is always taking the text from the str variable, how can I make it so that I loop through updated newStr, and replace all the values that match regex?

This works fine
Look at String.prototype.replace definition
const str = this.node.body;
const regex = /(href=\')([^\']*)(\')/g;
let newStr = str.replace(/(href=\')([^\']*)(\')/g, '$& target="_blank"')

Related

How to regex, and add "-" between words?

UPDATED
I been looking around in the old interweb to see if there is any way I can regex this as part of a replace method I'm doing: str.replace(/\w[A-Z]/gm, "-")
thisIsARegex
into this:
this-Is-A-Regex
I tried to mess around on regex101 with matching a \w character followed by [A-Z] but failed.
Any thoughts?
If the first char can't be uppercase:
var str = "thisIsARegex";
str = str.replace(/(?=[A-Z])/g, "-");
console.log(str); // this-Is-A-Regex
If the first char can be uppercase:
var str = "ThisIsARegex";
str = str.replace(/.(?=[A-Z])/g, "$&-");
console.log(str); // This-Is-A-Regex
or
var str = "ThisIsARegex";
str = str.replace(/\B(?=[A-Z])/g, "-");
console.log(str); // This-Is-A-Regex
(Last snippet suggested by #Thomas.)
var s = "thisIsARegex";
s = s.replace(/([A-Z])/g, '-$1').trim();
console.log(s);
Try this one:
you can check regex on this page and make your own tests:
https://regexr.com/
// initial value
let text = "thisIsARegexText";
// select Uppercase characters
let regexPattern = /[^a-z]/g;
// dump temp array
let newText = [];
// go through all characters, find Uppercase and replace with "-UppercaseCharacter"
for(i of text){
newText.push(i.replace(/[^a-z]/g, "-" + i))
}
// assign the result to the initial variable
text = newText.join("");

Split a string and get the second last comma

I have a string "Fred/Jim/Rob/"
What I needed is I need the split the string till last and also avoid the last /.
I have tried with:
for (var i = 0; i < input.length; i++) {
var input = ["Fred/Jim/Rob/"]
var X = input.split("/",);
----some other code---
}
In that case, my loop is running till last /, So I want to just avoid last /.
Consider using .match instead - match non-/ characters with a regular expression:
const str = "Fred/Jim/Rob/";
const result = str.match(/[^/]+/g);
console.log(result);
You might also split on a forward slash / and filter the empty entries afterwards using Boolean.
const input = "Fred/Jim/Rob/";
const result = input.split("/");
console.log(result.filter(Boolean));
You can simply remove the last / and split,
let str = "Fred/Jim/Rob/"
let str2 = "Fred/Jim/Rob"
let newStr =(str)=> (str.endsWith('/') ? str.substr(0,str.length-1) : str).split('/')
console.log(newStr(str))
console.log(newStr(str2))
You can try following :
words = "Fred/Jim/Rob/".split('/');
words.pop();
console.log(words);
It is possible to use split method:
let input = "Fred/Jim/Rob/";
let [fred, jim, Rob] = input.split(/[ / ]/);
console.log([fred, jim, Rob]);
try something like this:
var input = ["Fred/Jim/Rob/"];
var slices = input.split("/");
console.log(slices[slices.length-1]);

Split and replace text by two rules (regex)

I trying to split text by two rules:
Split by whitespace
Split words greater than 5 symbols into two separate words like (aaaaawww into aaaaa- and www)
I create regex that can detect this rules (https://regex101.com/r/fyskB3/2) but can't understand how to make both rules work in (text.split(/REGEX/)
Currently regex - (([\s]+)|(\w{5})(?=\w))
For example initial text is hello i am markopollo and result should look like ['hello', 'i', 'am', 'marko-', 'pollo']
It would probably be easier to use .match: match up to 5 characters that aren't whitespace:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer';
console.log(
str.match(/[^ ]{1,5}/g)
)
My approach would be to process the string before splitting (I'm a big fan of RegEx):
1- Search and replace all the 5 consecutive non-last characters with \1-.
The pattern (\w{5}\B) will do the trick, \w{5} will match 5 exact characters and \B will match only if the last character is not the ending character of the word.
2- Split the string by spaces.
var text = "hello123467891234 i am markopollo";
var regex = /(\w{5}\B)/g;
var processedText = text.replace(regex, "$1- ");
var result = processedText.split(" ");
console.log(result)
Hope it helps!
Something like this should work:
const str = "hello i am markopollo";
const words = str.split(/\s+/);
const CHUNK_SIZE=5;
const out = [];
for(const word of words) {
if(word.length > CHUNK_SIZE) {
let chunks = chunkSubstr(word,CHUNK_SIZE);
let last = chunks.pop();
out.push(...chunks.map(c => c + '-'),last);
} else {
out.push(word);
}
}
console.log(out);
// credit: https://stackoverflow.com/a/29202760/65387
function chunkSubstr(str, size) {
const numChunks = Math.ceil(str.length / size)
const chunks = new Array(numChunks)
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
chunks[i] = str.substr(o, size)
}
return chunks
}
i.e., first split the string into words on spaces, and then find words longer than 5 chars and 'chunk' them. I popped off the last chunk to avoid adding a - to it, but there might be a more efficient way if you patch chunkSubstr instead.
regex.split doesn't work so well because it will basically remove those items from the output. In your case, it appears you want to strip the whitespace but keep the words, so splitting on both won't work.
Uses the regex expression of #CertainPerformance = [^\s]{1,5}, then apply regex.exec, finally loop all matches to reach the goal.
Like below demo:
const str = 'wqerweirj ioqwejr qiwejrio jqoiwejr qwer qwer'
let regex1 = RegExp('[^ ]{1,5}', 'g')
function customSplit(targetString, regexExpress) {
let result = []
let matchItem = null
while ((matchItem = regexExpress.exec(targetString)) !== null) {
result.push(
matchItem[0] + (
matchItem[0].length === 5 && targetString[regexExpress.lastIndex] && targetString[regexExpress.lastIndex] !== ' '
? '-' : '')
)
}
return result
}
console.log(customSplit(str, regex1))
console.log(customSplit('hello i am markopollo', regex1))

Javascript regex to add to every character of a string a backslash

So as the title says I'd like to add to every character of a string a backslash, whether the string has special characters or not. The string should not be considered 'safe'
eg:
let str = 'dj%^3&something';
str = str.replace(x, y);
// str = '\d\j\%\^\3\&\s\o\m\e\t\h\i\n\g'
You could capture every character in the string with (.) and use \\$1 as replacement, I'm not an expert but basically \\ will render to \ and $1 will render to whatever (.) captures.
HIH
EDIT
please refer to Wiktor Stribiżew's comment for an alternative which will require less coding. Changes as follows:
str = str.replace(/(.)/g, '\\$1'); for str = str.replace(/./g, '\\$&');
Also, for future reference I strongly advice you to visit regexr.com when it comes to regular expressions, it's helped ME a lot
let str = 'dj%^3&something';
str = str.replace(/(.)/g, '\\$1');
console.log(str);
If you just want to display a string safely, you should just do:
let str = 'dj%^3&something';
let node = document.createTextNode(str);
let dest = document.querySelector('.whatever');
dest.appendChild(node);
And then you are guaranteed that it will be treated as text, and won't be able to execute a script or anything.
For example: https://jsfiddle.net/s6udj03L/1/
You can split the string to an array, add a \ to each element to the array, then joint the array back to the string that you wanted.
var str = 'dj%^3&something';
var split = str.split(""); // split string into array
for (var i = 0; i < split.length; i++) {
split[i] = '\\' + split[i]; // add backslash to each element in array
}
var joint = split.join('') // joint array to string
console.log(joint);
If you don't care about creating a new string and don't really have to use a regex, why not just iterate over the existing one and place a \ before each char. Notice to you have to put \\ to escape the first \.
To consider it safe, you have to encode it somehow. You could replace typical 'non-safe' characters like in the encode() function below. Notice how & get's replaced by &
let str = 'dj%^3&something';
let out = "";
for(var i = 0; i < str.length; i++) {
out += ("\\" + str[i]);
}
console.log(out);
console.log(encode(out));
function encode(string) {
return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}

Bold part of String

What is the best way to bold a part of string in Javascript?
I have an array of objects. Each object has a name. There is also an input parameter.
If, for example, you write "sa" in input, it automatically searches in array looking for objects with names that contain "sa" string.
When I print all the names, I want to bold the part of the name that coincide with the input text.
For example, if I search for "Ma":
Maria
Amaria
etc...
I need a solution that doesn't use jQuery. Help is appreciated.
PD: The final strings are in the tag. I create a list using angular ng-repeat.
This is the code:
$scope.users = data;
for (var i = data.length - 1; i >= 0; i--) {
data[i].name=data[i].name.replace($scope.modelCiudad,"<b>"+$scope.modelCiudad+"</b>");
};
ModelCiudad is the input text content var. And data is the array of objects.
In this code if for example ModelCiudad is "ma" the result of each is:
<b>Ma</b>ria
not Maria
You can use Javascript's str.replace() method, where str is equal to all of the text you want to search through.
var str = "Hello";
var substr = "el";
str.replace(substr, '<b>' + substr + '</b>');
The above will only replace the first instance of substr. If you want to handle replacing multiple substrings within a string, you have to use a regular expression with the g modifier.
function boldString(str, substr) {
var strRegExp = new RegExp(substr, 'g');
return str.replace(strRegExp, '<b>'+substr+'</b>');
}
In practice calling boldString would looks something like:
boldString("Hello, can you help me?", "el");
// Returns: H<b>el</b>lo can you h<b>el</b>p me?
Which when rendered by the browser will look something like: Hello can you help me?
Here is a JSFiddle with an example: https://jsfiddle.net/1rennp8r/3/
A concise ES6 solution could look something like this:
const boldString = (str, substr) => str.replace(RegExp(substr, 'g'), `<b>${substr}</b>`);
Where str is the string you want to modify, and substr is the substring to bold.
ES12 introduces a new string method str.replaceAll() which obviates the need for regex if replacing all occurrences at once. It's usage in this case would look something like this:
const boldString = (str, substr) => str.replaceAll(substr, `<b>${substr}</b>`);
I should mention that in order for these latter approaches to work, your environment must support ES6/ES12 (or use a tool like Babel to transpile).
Another important note is that all of these approaches are case sensitive.
Here's a pure JS solution that preserves the original case (ignoring the case of the query thus):
const boldQuery = (str, query) => {
const n = str.toUpperCase();
const q = query.toUpperCase();
const x = n.indexOf(q);
if (!q || x === -1) {
return str; // bail early
}
const l = q.length;
return str.substr(0, x) + '<b>' + str.substr(x, l) + '</b>' + str.substr(x + l);
}
Test:
boldQuery('Maria', 'mar'); // "<b>Mar</b>ia"
boldQuery('Almaria', 'Mar'); // "Al<b>mar</b>ia"
I ran into a similar problem today - except I wanted to match whole words and not substrings. so if const text = 'The quick brown foxes jumped' and const word = 'foxes' than I want the result to be 'The quick brown <strong>foxes</strong> jumped'; however if const word = 'fox', than I expect no change.
I ended up doing something similar to the following:
const pattern = `(\\s|\\b)(${word})(\\s|\\b)`;
const regexp = new RegExp(pattern, 'ig'); // ignore case (optional) and match all
const replaceMask = `$1<strong>$2</strong>$3`;
return text.replace(regexp, replaceMask);
First I get the exact word which is either before/after some whitespace or a word boundary, and then I replace it with the same whitespace (if any) and word, except the word is wrapped in a <strong> tag.
Here is a version I came up with if you want to style words or individual characters at their index in react/javascript.
replaceAt( yourArrayOfIndexes, yourString/orArrayOfStrings )
Working example: https://codesandbox.io/s/ov7zxp9mjq
function replaceAt(indexArray, [...string]) {
const replaceValue = i => string[i] = <b>{string[i]}</b>;
indexArray.forEach(replaceValue);
return string;
}
And here is another alternate method
function replaceAt(indexArray, [...string]) {
const startTag = '<b>';
const endTag = '</b>';
const tagLetter = i => string.splice(i, 1, startTag + string[i] + endTag);
indexArray.forEach(tagLetter);
return string.join('');
}
And another...
function replaceAt(indexArray, [...string]) {
for (let i = 0; i < indexArray.length; i++) {
string = Object.assign(string, {
[indexArray[i]]: <b>{string[indexArray[i]]}</b>
});
}
return string;
}
Above solutions are great, but are limited! Imagine a test scenerio where you want to match case insensitive query in a string and they could be multiple matches.
For example
Query: ma
String: The Amazing Spiderman
Expected Result: The Amazing Spiderman
For above scenerio, use this:
const boldMatchText = (text,searchInput) => {
let str = text.toLowerCase();
const query = searchInput.toLowerCase();
let result = "";
let queryLoc = str.indexOf(query);
if (queryLoc === -1) {
result += text;
} else
do {
result += ` ${text.substr(0, queryLoc)}
<b>${text.substr(queryLoc, query.length)}</b>`;
str = str.substr(queryLoc + query.length, str.length);
text = text.substr(queryLoc + query.length, str.length);
queryLoc = str.indexOf(query);
} while (text.length > 0 && queryLoc !== -1);
return result + text;
};

Categories

Resources