How to replace all capture groups if it is generated dynamically? - javascript

Consider the following code:
function Matcher(source, search) {
var opts = search.split('');
for (var i = 0; i < opts.length; i++) {
opts[i] = '(' + opts[i] + ')';
}
opts = opts.join('.*');
var regexp = new RegExp(opts, 'gi');
source = source.replace(regexp, function () {
console.log(arguments);
return arguments[1];
});
return source;
}
You call the function passing the source as the first parameter and what you need to match as the second one.
What i need is to replace all capture groups with a bold tag around the coincidence.
As an example, consider the following:
var patt = /m([a-z0-9\-_]*?)r([a-z0-9\-_]*?)i([a-z0-9\-_]*?)e([a-z0-9\-_]*\.[a-z]+)/gi;
var newFileName = fileName.replace(patt, "<strong>m</strong>$1<strong>r</strong>$2<strong>i</strong>$3<strong>e</strong>$4");
This code is an answer from Terry on my previous question but the problem here is that you need to know exactly what you want to replace, and i need it dynamically.
Any thoughts?

It seems like you're creating the pattern the wrong way round. Instead of building a(.*?)b(.*?)c, you create (a).*(b).*(c) - with the capturing groups around the parts you already know. Better:
function wrapEachLetter(source, search, tag) {
var opts = search.split('');
tag = tag || "strong";
return source.replace(new RegExp(opts.join("(.*?)"), 'gi'), function () {
var str = '<'+tag+'>'+opts[0]+'</'+tag+'>';
for (var i=1; i<opts.length; i++)
str += arguments[i] + '<'+tag+'>'+opts[i]+'</'+tag+'>';
return str;
});
}
Example:
> wrapEachLetter("testExampleString", "tex", "b")
"<b>t<b><b>e<b>stE<b>x<b>ampleString"

Capture the delimiters too and then process only even subgroups, leaving odd ones as is:
s = "ABC---DEF---HIJ"
re = /(\w+)(.*?)(\w+)(.*?)(\w+)/
s.replace(re, function() {
return [].slice.call(arguments, 1, -2).map(function(a, n) {
return n & 1 ? a : "<strong>" + a + "</strong>"
}).join("")
})
> "<strong>ABC</strong>---<strong>DEF</strong>---<strong>HIJ</strong>"
However, if your goal is to highlight only individual characters, it's much simpler this way:
str = "myfile.js"
letters = "mis"
re = new RegExp("[" + letters + "]", "gi")
str.replace(re, "<b>$&</b>")
> "<b>m</b>yf<b>i</b>le.j<b>s</b>"
or, without regular expressions:
str = "myfile.js"
letters = "mis"
str.split("").map(function(s) {
return letters.indexOf(s) >= 0 ? "<b>" + s + "</b>" : s
}).join("")
> "<b>m</b>yf<b>i</b>le.j<b>s</b>"

var input = "aBcDeFgHiJk",
match = 'be';
str = '',
reg = '',
i = 0;
function escapeRegExp(c) {
return c.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
// /(.*)(b)(.*)(e)(.*)/gi
// '$1<b>$2</b>$3<b>$4</b>$5'
for (var c in match) {
if (i == 0) {
str += '$' + ++i;
reg += '(.*)';
i++;
}
str += '<b>$' + i++ + '</b>$' + i++;
reg += '(' + escapeRegExp(match[c]) + ')(.*)';
}
alert(input.replace(new RegExp(reg, 'ig'), str)); // <- a<b>B</b>cD<b>e</b>FgHiJk

Related

Checking if a string isn't a space in Javascript

So I have a program that counts the words in a document that is loaded into an iFrame, all of the newline characters are replaced by a space, then the string is split by spaces, I then want to add them to a map as the key and set their value to 1 if they're not in the map or not a space, this is where I'm having the problem because it's still counting each space in the string , I feel like I'm being really stupid and missing something obvious...
var innerDoc = document.getElementById("pageinframe");
var innerDocContent = innerDoc.contentDocument.body.innerHTML;
var split = strip(innerDocContent).replace(/(\r\n|\n|\r)/gm, " ").split(" ");
var obj = new Map();
for (var x = 0; x < split.length; x++) {
console.dir(typeof split[x]);
if(!obj.has(split[x]) && (split[x] != " ")) {
obj.set(split[x], 1);
}
else if (split[x] != " ") {
obj.set(split[x], obj.get(split[x])+1);
}
}
function strip(str) {
var tmp = document.createElement("DIV");
tmp.innerHTML = str;
return tmp.textContent || tmp.innerText || "";
}
There are something, icant understand. When you split(' '). the array not contains ' ', only words!!!, https://www.w3schools.com/jsref/jsref_split.asp. Son Why need to testif is white space. Then i think, it could be in:
.replace(/(\r\n|\n|\r)/gm, " ")
The split array contained "" not " " like I originally thought. Like I said I was missing something really obvious, just needed to see what was in the array.
var innerDoc = document.getElementById("pageinframe");
var innerDocContent = innerDoc.contentDocument.body.innerHTML;
var split = strip(innerDocContent).replace(/(\r\n|\n|\r)/gm, " ").split(" ");
var obj = new Map();
for (var x = 0; x < split.length; x++) {
// Removing NaN for string
if(split[x].charCodeAt(0))
{
if(!obj.has(split[x]) && (split[x] != " ")) {
obj.set(split[x], 1);
}
else if (split[x] != " ") {
obj.set(split[x], obj.get(split[x])+1);
}
}
}
function strip(str) {
var tmp = document.createElement("DIV");
tmp.innerHTML = str;
return tmp.textContent || tmp.innerText || "";
}
console.log(obj);

JavaScript replace all of linebreaks [duplicate]

Is there an easy equivalent to this in JavaScript?
$find = array("<", ">", "\n");
$replace = array("<", ">", "<br/>");
$textarea = str_replace($find, $replace, $textarea);
This is using PHP's str_replace, which allows you to use an array of words to look for and replace. Can I do something like this using JavaScript / jQuery?
...
var textarea = $(this).val();
// string replace here
$("#output").html(textarea);
...
You could extend the String object with your own function that does what you need (useful if there's ever missing functionality):
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
for (var i = 0; i < find.length; i++) {
replaceString = replaceString.replace(find[i], replace[i]);
}
return replaceString;
};
For global replace you could use regex:
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
var regex;
for (var i = 0; i < find.length; i++) {
regex = new RegExp(find[i], "g");
replaceString = replaceString.replace(regex, replace[i]);
}
return replaceString;
};
To use the function it'd be similar to your PHP example:
var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
textarea = textarea.replaceArray(find, replace);
Common Mistake
Nearly all answers on this page use cumulative replacement and thus suffer the same flaw where replacement strings are themselves subject to replacement. Here are a couple examples where this pattern fails (h/t #KurokiKaze #derekdreery):
function replaceCumulative(str, find, replace) {
for (var i = 0; i < find.length; i++)
str = str.replace(new RegExp(find[i],"g"), replace[i]);
return str;
};
// Fails in some cases:
console.log( replaceCumulative( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceCumulative( "you & me", ['you','me'], ['me','you'] ) );
Solution
function replaceBulk( str, findArray, replaceArray ){
var i, regex = [], map = {};
for( i=0; i<findArray.length; i++ ){
regex.push( findArray[i].replace(/([-[\]{}()*+?.\\^$|#,])/g,'\\$1') );
map[findArray[i]] = replaceArray[i];
}
regex = regex.join('|');
str = str.replace( new RegExp( regex, 'g' ), function(matched){
return map[matched];
});
return str;
}
// Test:
console.log( replaceBulk( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceBulk( "you & me", ['you','me'], ['me','you'] ) );
Note:
This is a more compatible variation of #elchininet's solution, which uses map() and Array.indexOf() and thus won't work in IE8 and older.
#elchininet's implementation holds truer to PHP's str_replace(), because it also allows strings as find/replace parameters, and will use the first find array match if there are duplicates (my version will use the last). I didn't accept strings in this implementation because that case is already handled by JS's built-in String.replace().
text = text.replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br/>');
A more visual approach:
String.prototype.htmlProtect = function() {
var replace_map;
replace_map = {
'\n': '<br />',
'<': '<',
'>': '>'
};
return this.replace(/[<>\n]/g, function(match) { // be sure to add every char in the pattern
return replace_map[match];
});
};
and this is how you call it:
var myString = "<b>tell me a story, \n<i>bro'</i>";
var myNewString = myString.htmlProtect();
// <b>tell me a story, <br /><i>bro'</i>
You could use the replace method of the String object with a function in the second parameter to avoid replacing a string that was previously replaced:
First Method (using a find and replace Object)
var findreplace = {"<" : "<", ">" : ">", "\n" : "<br/>"};
textarea = textarea.replace(new RegExp("(" + Object.keys(findreplace).map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return findreplace[s]});
jsfiddle
Second method (using two arrays, find and replace)
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
textarea = textarea.replace(new RegExp("(" + find.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return replace[find.indexOf(s)]});
jsfiddle
Desired function:
function str_replace($f, $r, $s){
return $s.replace(new RegExp("(" + $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return $r[$f.indexOf(s)]});
}
$textarea = str_replace($find, $replace, $textarea);
EDIT
This function admits a String or an Array as parameters:
function str_replace($f, $r, $s){
return $s.replace(new RegExp("(" + (typeof($f) === "string" ? $f.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&") : $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|")) + ")", "g"), typeof($r) === "string" ? $r : typeof($f) === "string" ? $r[0] : function(i){ return $r[$f.indexOf(i)]});
}
A simple forEach loop solves this quite well:
let text = 'the red apple and the green ball';
const toStrip = ['red', 'green'];
toStrip.forEach(x => {
text = text.replace(x, '');
});
console.log(text);
// logs -> the apple and the ball
The top answer is equivalent to doing:
let text = find.reduce((acc, item, i) => {
const regex = new RegExp(item, "g");
return acc.replace(regex, replace[i]);
}, textarea);
Given this:
var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
In this case, no imperative programming is going on.
Using ES6:
There are many ways to search for strings and replace in JavaScript. One of them is as follow
const findFor = ['<', '>', '\n'];
const replaceWith = ['<', '>', '<br/>'];
const originalString = '<strong>Hello World</strong> \n Let\'s code';
let modifiedString = originalString;
findFor.forEach( (tag, i) => modifiedString = modifiedString.replace(new RegExp(tag, "g"), replaceWith[i]) )
console.log('Original String: ', originalString);
console.log('Modified String: ', modifiedString);
You might want to look into a JS library called phpJS.
It allows you to use the str_replace function similarly to how you would use it in PHP. There are also plenty more php functions "ported" over to JavaScript.
http://phpjs.org/functions/str_replace:527
String.prototype.replaceArray = function (find, replace) {
var replaceString = this;
for (var i = 0; i < find.length; i++) {
// global replacement
var pos = replaceString.indexOf(find[i]);
while (pos > -1) {
replaceString = replaceString.replace(find[i], replace[i]);
pos = replaceString.indexOf(find[i]);
}
}
return replaceString;
};
var textT = "Hello world,,,,, hello people.....";
var find = [".",","];
var replace = ['2', '5'];
textT = textT.replaceArray(find, replace);
// result: Hello world55555 hello people22222
const items = {
'<': '<',
'>': '>',
'\n': '<br/>',
}
const re = new RegExp('[' + Object.keys(items).join('') + ']', 'g')
const input = '<foo>\n<bar>'
const output = input.replaceAll(re, key => items[key])
console.log(output)
There is no way to do this in one method call, you'll have to either chain calls together, or write a function that manually does what you need.
var s = "<>\n";
s = s.replace("<", "<");
s = s.replace(">", ">");
s = s.replace("\n", "<br/>");
For the tags, you should be able to just set the content with .text() instead of .html().
Example: http://jsfiddle.net/Phf4u/1/
var textarea = $('textarea').val().replace(/<br\s?\/?>/, '\n');
$("#output").text(textarea);
...or if you just wanted to remove the <br> elements, you could get rid of the .replace(), and temporarily make them DOM elements.
Example: http://jsfiddle.net/Phf4u/2/
var textarea = $('textarea').val();
textarea = $('<div>').html(textarea).find('br').remove().end().html();
$("#output").text(textarea);
A version with an object as a parameter:
String.prototype.strtr = function (replace) {
keys = Object.keys(replace);
result = this;
for (i = 0; i < keys.length; i++) {
result = result.replace(keys[i], replace[keys[i]]);
}
return result;
}
function htmlspecialchars(str) {
return String(str).strtr({">": ">", "<": "<", "\n": "<br/>"});
}
// usage
text = "<span>spam</span>";
htmlspecialchars(text);
jquery have a solution for that.
var htmlString = $( element).html();
$( element ).text( htmlString );
view here:
https://api.jquery.com/html/
wrap all this in a function, you can pass both an array and a string
function str_replace(search,replace,subject) {
if(!Array.isArray(search)){
subject = subject.replace(new RegExp(search, "g"), replace)
}
else{
search.forEach( (tag, i) => subject = subject.replace(new RegExp(tag, "g"), replace[i]) )
}
return subject;
}
Just that!
let v = "Test's <<foo>> ((baAr))";
console.log(v);
const r = ['<', '>', 'a', '\\)', '\\(', '\'' ];
for (var i = r.length - 1; i >= 0; i--) {
v = v.replace((new RegExp(r[i], "gi")), "_");
}
console.log(v);
One method would be:
var text = $(this).val();
text = text.replace(/</g, "<").replace(/>/g, ">");
$("#output").html(text);

How to join a string in javascript based on a regex or if string starts with some value?

for instance I have this string:
013227004871996 300234060903250 013227003498171 013227003493834 300234010640390
013227003512963 300234061401690 013227004865956 013226009142122 013227008391574
300234061405690 013227003400573 300234061404700 013227003501479 013227003394495
013227004876284 300234061349230 013227004876284 013227004862011
and what I want to happen is that to separate the entry if it encounters 01322, so for instance in the example it will have array[0] = 013227004871996 300234060903250, array[1] = 013227003498171,
array[2] = 013227003493834
so basically I want to split it if the next entry starts with "013227".
This seems to work. Im matching everything that starts and is followed by 013227. Then I'm matching the last segment with .+
str.match(/013227.+?(?=013227)|.+/g)
Or even better:
str.split(/(?=013227)/)
var numbersStr = "013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 013227004876284 300234061349230 013227004876284 013227004862011";
var pattern = new RegExp('01322[\\d]+');
var numbersArr = numbersStr.split(' ');
var numbersArrLength = numbersArr.length - 1;
for (var i = numbersArrLength; i >= 0; i--) {
if (!pattern.test(numbersArr[i])) {
numbersArr.splice(i, 1);
}
}
var separator = '01322';
"013227004871996 300234060903250 013227003498171 013227003493834 300234010640390"
.split(separator)
.filter(function(item){
return item;
}).map(function(item){
return separator + item;
})
var s = "013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 "
+ "013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 "
+ "300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 "
+ "013227004876284 300234061349230 013227004876284 013227004862011";
var sp = s.split(" ");
var res = new Array();
var count=0;
sp.forEach(function(a) {
if(a.search("01322") === 0) {
if(res[count] === undefined) {
res[count] = a;
} else {
++count;
res[count] = a;
}
} else {
if(res[count] === undefined) {
res[count] = a;
} else {
res[count]+=" "+a;
}
}
});
console.log(res);
[ '013227004871996 300234060903250',
'013227003498171',
'013227003493834 300234010640390',
'013227003512963 300234061401690',
'013227004865956',
'013226009142122',
'013227008391574 300234061405690',
'013227003400573 300234061404700',
'013227003501479',
'013227003394495',
'013227004876284 300234061349230',
'013227004876284',
'013227004862011' ]
try this
function niceslice( string, delimiter ){
var result = string.split(delimiter);
for(var i = 1; i < result.length; i++){
result[i] = delimiter + result[i];
}
return result;
}
take note that this will not eliminate spaces in your example (but should be easily built in)
example usage
var str = 'anton albert andrew';
var output = niceslice( str, 'a' );
console.log( output ); // returns ['', 'anton ', 'albert ', 'andrew']
or in your case
var str = '013227004871996 300234060903250 013227003498171 013227003493834 300234010640390 013227003512963 300234061401690 013227004865956 013226009142122 013227008391574 300234061405690 013227003400573 300234061404700 013227003501479 013227003394495 013227004876284 300234061349230 013227004876284 013227004862011';
var output = niceslice( str, '013227' );

How to replace only first sequential occurences (fuzzymatch)?

I'm trying to write "fuzzy" match and I can't find a way to solve this problem:
Data in: makrusakkk, query: mrk, expected result: <b>m</b>ak<b>r</b>usa<b>k</b>kk.
RegExp: "makrusakkk".match(/(m).*?(r).*?(k)/i) returns ["makrusak", "m", "r", "k"].
So the question is: is there a way to get the expected result using RegExp?
I think using regular expression for such problem makes things just more complicated. The following string and loop based solution would lead to the result:
function fuzzySearch(query, input) {
var inds = patternMatches(query, input);
if(!inds) return input;
var result = input;
for(var i = inds.length - 1; i >= 0; i--) {
var index = inds[i];
result = result.substr(0,index) +
"<b>" + result[index] + "</b>" +
result.substr(index+1);
}
return result;
}
function patternMatches(query, input) {
if(query.length <= 0) {
return [];
} else if(query.length == 1) {
if(input[0] == query[0]) return [0];
else return [];
} else {
if(input[0] != query[0])
return false;
var inds = [0];
for(var i = 1; i < query.length; i++) {
var foundInd = input.indexOf(query[i], inds[i-1]);
if(foundInd < 0) {
return [];
} else {
inds.push(foundInd);
}
}
return inds;
}
}
var input = "makrusakkksd";
var query = "mrk";
console.log(fuzzySearch(query, input));
console.log(patternMatches(query, input));
Here's a live demo too: http://jsfiddle.net/sinairv/T2MF4/
Here you will need for:
function search_for_it(txt, arr){
for(i=0;i<arr.length;i++){
var reg = new RegExp(arr[i], "i");
txt = txt.replace(reg, "<b>"+arr[i]+"</b>");
}
return txt;
}
search_for_it("makrusakkk", ["m","r","k"]);
//return "<b>m</b>a<b>k</b><b>r</b>usakkk"
PS: Your expected result is incorrect. There is a k after the first a.
is there a way to get an expected result using RegExp?
There is.
"makrusakkk".replace(/(m)(.*?)(r)(.*?)(k)/i, '<b>$1</b>$2<b>$3</b>$4<b>$5</b>'​​​​​​​)
I feel vaguely dirty for this, but...regardless; here's one way to do it:
$('#s').keyup(
function(e) {
var w = e.which;
if (w == 8 || w == 46) {
return false;
}
var listElems = $('ul:first li'),
search = $(this).val().replace(/w+/g, ''),
r = search.split(''),
rString = [];
$.each(r, function(i, v) {
rString.push('(' + v + ')');
});
var reg = new RegExp(rString.join('(\\d|\\D)*'), 'gi');
listElems.each(
function() {
if (!$(this).attr('data-origtext')) {
$(this).attr('data-origtext', $(this).text());
}
$(this).html($(this).attr('data-origtext').replace(reg, '<b>$&</b>'));
});
});​
JS Fiddle demo.
It could, almost certainly, benefit from quite some simplification though.
References:
attr().
:first selector.
join().
keyup().
push().
RegExp().
replace().
split().
text().
val().

Replace multiple strings at once

Is there an easy equivalent to this in JavaScript?
$find = array("<", ">", "\n");
$replace = array("<", ">", "<br/>");
$textarea = str_replace($find, $replace, $textarea);
This is using PHP's str_replace, which allows you to use an array of words to look for and replace. Can I do something like this using JavaScript / jQuery?
...
var textarea = $(this).val();
// string replace here
$("#output").html(textarea);
...
You could extend the String object with your own function that does what you need (useful if there's ever missing functionality):
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
for (var i = 0; i < find.length; i++) {
replaceString = replaceString.replace(find[i], replace[i]);
}
return replaceString;
};
For global replace you could use regex:
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
var regex;
for (var i = 0; i < find.length; i++) {
regex = new RegExp(find[i], "g");
replaceString = replaceString.replace(regex, replace[i]);
}
return replaceString;
};
To use the function it'd be similar to your PHP example:
var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
textarea = textarea.replaceArray(find, replace);
Common Mistake
Nearly all answers on this page use cumulative replacement and thus suffer the same flaw where replacement strings are themselves subject to replacement. Here are a couple examples where this pattern fails (h/t #KurokiKaze #derekdreery):
function replaceCumulative(str, find, replace) {
for (var i = 0; i < find.length; i++)
str = str.replace(new RegExp(find[i],"g"), replace[i]);
return str;
};
// Fails in some cases:
console.log( replaceCumulative( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceCumulative( "you & me", ['you','me'], ['me','you'] ) );
Solution
function replaceBulk( str, findArray, replaceArray ){
var i, regex = [], map = {};
for( i=0; i<findArray.length; i++ ){
regex.push( findArray[i].replace(/([-[\]{}()*+?.\\^$|#,])/g,'\\$1') );
map[findArray[i]] = replaceArray[i];
}
regex = regex.join('|');
str = str.replace( new RegExp( regex, 'g' ), function(matched){
return map[matched];
});
return str;
}
// Test:
console.log( replaceBulk( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceBulk( "you & me", ['you','me'], ['me','you'] ) );
Note:
This is a more compatible variation of #elchininet's solution, which uses map() and Array.indexOf() and thus won't work in IE8 and older.
#elchininet's implementation holds truer to PHP's str_replace(), because it also allows strings as find/replace parameters, and will use the first find array match if there are duplicates (my version will use the last). I didn't accept strings in this implementation because that case is already handled by JS's built-in String.replace().
text = text.replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br/>');
A more visual approach:
String.prototype.htmlProtect = function() {
var replace_map;
replace_map = {
'\n': '<br />',
'<': '<',
'>': '>'
};
return this.replace(/[<>\n]/g, function(match) { // be sure to add every char in the pattern
return replace_map[match];
});
};
and this is how you call it:
var myString = "<b>tell me a story, \n<i>bro'</i>";
var myNewString = myString.htmlProtect();
// <b>tell me a story, <br /><i>bro'</i>
You could use the replace method of the String object with a function in the second parameter to avoid replacing a string that was previously replaced:
First Method (using a find and replace Object)
var findreplace = {"<" : "<", ">" : ">", "\n" : "<br/>"};
textarea = textarea.replace(new RegExp("(" + Object.keys(findreplace).map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return findreplace[s]});
jsfiddle
Second method (using two arrays, find and replace)
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
textarea = textarea.replace(new RegExp("(" + find.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return replace[find.indexOf(s)]});
jsfiddle
Desired function:
function str_replace($f, $r, $s){
return $s.replace(new RegExp("(" + $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|") + ")", "g"), function(s){ return $r[$f.indexOf(s)]});
}
$textarea = str_replace($find, $replace, $textarea);
EDIT
This function admits a String or an Array as parameters:
function str_replace($f, $r, $s){
return $s.replace(new RegExp("(" + (typeof($f) === "string" ? $f.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&") : $f.map(function(i){return i.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")}).join("|")) + ")", "g"), typeof($r) === "string" ? $r : typeof($f) === "string" ? $r[0] : function(i){ return $r[$f.indexOf(i)]});
}
A simple forEach loop solves this quite well:
let text = 'the red apple and the green ball';
const toStrip = ['red', 'green'];
toStrip.forEach(x => {
text = text.replace(x, '');
});
console.log(text);
// logs -> the apple and the ball
The top answer is equivalent to doing:
let text = find.reduce((acc, item, i) => {
const regex = new RegExp(item, "g");
return acc.replace(regex, replace[i]);
}, textarea);
Given this:
var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["<", ">", "<br/>"];
In this case, no imperative programming is going on.
Using ES6:
There are many ways to search for strings and replace in JavaScript. One of them is as follow
const findFor = ['<', '>', '\n'];
const replaceWith = ['<', '>', '<br/>'];
const originalString = '<strong>Hello World</strong> \n Let\'s code';
let modifiedString = originalString;
findFor.forEach( (tag, i) => modifiedString = modifiedString.replace(new RegExp(tag, "g"), replaceWith[i]) )
console.log('Original String: ', originalString);
console.log('Modified String: ', modifiedString);
You might want to look into a JS library called phpJS.
It allows you to use the str_replace function similarly to how you would use it in PHP. There are also plenty more php functions "ported" over to JavaScript.
http://phpjs.org/functions/str_replace:527
String.prototype.replaceArray = function (find, replace) {
var replaceString = this;
for (var i = 0; i < find.length; i++) {
// global replacement
var pos = replaceString.indexOf(find[i]);
while (pos > -1) {
replaceString = replaceString.replace(find[i], replace[i]);
pos = replaceString.indexOf(find[i]);
}
}
return replaceString;
};
var textT = "Hello world,,,,, hello people.....";
var find = [".",","];
var replace = ['2', '5'];
textT = textT.replaceArray(find, replace);
// result: Hello world55555 hello people22222
const items = {
'<': '<',
'>': '>',
'\n': '<br/>',
}
const re = new RegExp('[' + Object.keys(items).join('') + ']', 'g')
const input = '<foo>\n<bar>'
const output = input.replaceAll(re, key => items[key])
console.log(output)
There is no way to do this in one method call, you'll have to either chain calls together, or write a function that manually does what you need.
var s = "<>\n";
s = s.replace("<", "<");
s = s.replace(">", ">");
s = s.replace("\n", "<br/>");
For the tags, you should be able to just set the content with .text() instead of .html().
Example: http://jsfiddle.net/Phf4u/1/
var textarea = $('textarea').val().replace(/<br\s?\/?>/, '\n');
$("#output").text(textarea);
...or if you just wanted to remove the <br> elements, you could get rid of the .replace(), and temporarily make them DOM elements.
Example: http://jsfiddle.net/Phf4u/2/
var textarea = $('textarea').val();
textarea = $('<div>').html(textarea).find('br').remove().end().html();
$("#output").text(textarea);
A version with an object as a parameter:
String.prototype.strtr = function (replace) {
keys = Object.keys(replace);
result = this;
for (i = 0; i < keys.length; i++) {
result = result.replace(keys[i], replace[keys[i]]);
}
return result;
}
function htmlspecialchars(str) {
return String(str).strtr({">": ">", "<": "<", "\n": "<br/>"});
}
// usage
text = "<span>spam</span>";
htmlspecialchars(text);
jquery have a solution for that.
var htmlString = $( element).html();
$( element ).text( htmlString );
view here:
https://api.jquery.com/html/
wrap all this in a function, you can pass both an array and a string
function str_replace(search,replace,subject) {
if(!Array.isArray(search)){
subject = subject.replace(new RegExp(search, "g"), replace)
}
else{
search.forEach( (tag, i) => subject = subject.replace(new RegExp(tag, "g"), replace[i]) )
}
return subject;
}
Just that!
let v = "Test's <<foo>> ((baAr))";
console.log(v);
const r = ['<', '>', 'a', '\\)', '\\(', '\'' ];
for (var i = r.length - 1; i >= 0; i--) {
v = v.replace((new RegExp(r[i], "gi")), "_");
}
console.log(v);
One method would be:
var text = $(this).val();
text = text.replace(/</g, "<").replace(/>/g, ">");
$("#output").html(text);

Categories

Resources