How to produce replacement for several substrings with single regex? - javascript

There is a source string containing some of the following substrings:
"first"
"second"
It is necessary to replace them correspondingly to
"third"
"forth"
I do that the following way
var output = input;
var re1 = /first/;
var re2 = /second/;
output = output.replace(re1, "third")
output = output.replace(re2, "forth")
The question is how to do that with single regular expression?

You can do it with a function passed to .replace():
output = output.replace(/first|second/g, function(word) {
return word === "first" ? "third" : "fourth";
});

You could probably do something like this; using an anonymous function:
var input = "This is the first... no second time that I tell you this!";
var result = input.replace(/first|second/g, function(m) {
switch(m)
{
case "first":
return "third";
case "second":
return "forth";
}
});
jsfiddle
The variable m will contain the match, passed to a switch where you can add more replacements if you need.

It is impossible unless you pass a function as the second argument.
var a =function(a){if(a=="first"){ a="third" }else{ a="forth"} return a}
output = output.replace(/first|second/g, a);
Then you may as well just write a one liner.
output = output.replace(/first/g, "third").replace(/second/g, "forth");

Related

How to get value in $1 in regex to a variable for further manipulation [duplicate]

You can backreference like this in JavaScript:
var str = "123 $test 123";
str = str.replace(/(\$)([a-z]+)/gi, "$2");
This would (quite silly) replace "$test" with "test". But imagine I'd like to pass the resulting string of $2 into a function, which returns another value. I tried doing this, but instead of getting the string "test", I get "$2". Is there a way to achieve this?
// Instead of getting "$2" passed into somefunc, I want "test"
// (i.e. the result of the regex)
str = str.replace(/(\$)([a-z]+)/gi, somefunc("$2"));
Like this:
str.replace(regex, function(match, $1, $2, offset, original) { return someFunc($2); })
Pass a function as the second argument to replace:
str = str.replace(/(\$)([a-z]+)/gi, myReplace);
function myReplace(str, group1, group2) {
return "+" + group2 + "+";
}
This capability has been around since Javascript 1.3, according to mozilla.org.
Using ESNext, quite a dummy links replacer but just to show-case how it works :
let text = 'Visit http://lovecats.com/new-posts/ and https://lovedogs.com/best-dogs NOW !';
text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => {
// remove ending slash if there is one
link = link.replace(/\/?$/, '');
return `${link.substr(link.lastIndexOf('/') +1)}`;
});
document.body.innerHTML = text;
Note: Previous answer was missing some code. It's now fixed + example.
I needed something a bit more flexible for a regex replace to decode the unicode in my incoming JSON data:
var text = "some string with an encoded 's' in it";
text.replace(/&#(\d+);/g, function() {
return String.fromCharCode(arguments[1]);
});
// "some string with an encoded 's' in it"
If you would have a variable amount of backreferences then the argument count (and places) are also variable. The MDN Web Docs describe the follwing syntax for sepcifing a function as replacement argument:
function replacer(match[, p1[, p2[, p...]]], offset, string)
For instance, take these regular expressions:
var searches = [
'test([1-3]){1,3}', // 1 backreference
'([Ss]ome) ([A-z]+) chars', // 2 backreferences
'([Mm][a#]ny) ([Mm][0o]r[3e]) ([Ww][0o]rd[5s])' // 3 backreferences
];
for (var i in searches) {
"Some string chars and many m0re w0rds in this test123".replace(
new RegExp(
searches[i]
function(...args) {
var match = args[0];
var backrefs = args.slice(1, args.length - 2);
// will be: ['Some', 'string'], ['many', 'm0re', 'w0rds'], ['123']
var offset = args[args.length - 2];
var string = args[args.length - 1];
}
)
);
}
You can't use 'arguments' variable here because it's of type Arguments and no of type Array so it doesn't have a slice() method.

JS - Have function repeat until condition met

this seems simple but I'm still having difficulty (I'm relatively new).
I have a function replaceNextParameter() which goes through a string and replaces text between two strings I notate as sub1 and sub2. A string may have 0, 1 or many sub1 and sub2 present. I would like it to execute function replaceNextparameter until there are no more sub1 and sub2 present and return the result.
Here is my code:
function findAllParametersInString (string, sub1, sub2, parameterAndInputArray) {
newString = string
if (newString.indexOf(sub1) > -1 && newString.indexOf(sub2) > -1) {
newString = replaceNextParameter(sub1, sub2, newString, parameterAndInputArray);
}
return newString
};
Here is a live example of what it should do.
//data:
const paramsArray = [
{param: "company", input: "COMPANY"},
{param: "url", input: "URL"},
]
const sampleMessage = "BlaBlaBla {{company}} and {{url}}"
findAllParametersInString(sampleMessage,'{{', '}}', paramsArray);
//Should return "BlaBlaBla COMPANY and URL"
Any idea how to fix it? Currently it only returns "BlaBlaBla COMPANY and {{url}}"
I suggest you to use your param value as key, and your input value as value in one single object. Like this:
var params = {
company: "COMPANY",
url: "URL"
};
and now use this simple function:
var sampleMessage = "BlaBlaBla {{company}} and {{url}}";
function replace(str, map) {
for (var key in map) {
str = str.split('{{' + key + '}}').join(map[key]);
}
return str;
}
replace(sampleMessage, params); // -> "BlaBlaBla COMPANY and URL"
You can use parameters for {{ and }} in replace function
Although late, yet I hope this solution might be suitable for someone.
The best solution I think, since it's string you want to deal with, is to use regular expression.
Although I'm not sure what the parameterAndInputArray is for though.
So I would use this (although a better regex can be created):
let newstring = oldstring.replace(/sub1/gi,replacement1).replace(/sub2/gi,replacement2)
where replacement[1/2] will be the character to be replaced eg('#') or empty quotes ('') if sub[1/2] are to be removed.
function findAllParametersInString (string, sub1, sub2, parameterAndInputArray) {
newString = string
while (newString.indexOf(sub1) > -1 && newString.indexOf(sub2) > -1) {
newString = replaceNextParameter(sub1, sub2, newString, parameterAndInputArray);
}
return newString
};
Did the trick based off of #Flemming

How to remove the comma(,) from the first position and last position of string

I want to remove the comma(,) from the the string if it occur at first position or last position in the string.
For Example :
var str = ",abcd,efg,last,";
The output should be
output = 'abcd,efg,last'
if input is
str = "abcdef,ghij,kl"
the output should be :
output = "abcdef,ghij,kl"
var str = ",abcd,efg,last,";
var res = str.replace(/^,|,$/g, '');
console.log(res);
do this
this will remove the comma if it is at the starting position or at the end of the string position
There must be some strip() function in Javascript that I don't know for lack of my knowledge. But here is how you can do it using regex:
output = ",abcd,efg,last,".replace(/^,|,$/g, "");
JavaScript doesn't include a native method for this. The closest is trim, but that doesn't take any args. I think it should, though. So you could write something like this
String.prototype.trim = (function (trim) {
if (!trim) // polyfill if not included in browser
trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
else if (trim.call('.', '.') === '') // already supports this
return trim;
return function (chars) {
if (!chars) return trim.call(this);
chars = chars.replace(/([\^\\\]-])/g, '\\$1');
return this.replace(new RegExp('^['+chars+']+|['+chars+']+$', 'g'), '');
}
}(String.prototype.trim));
Now we have
' foo '.trim(); // "foo"
',,,foo,,,'.trim(','); // "foo"

replace all commas within a quoted string

is there any way to capture and replace all the commas within a string contained within quotation marks and not any commas outside of it. I'd like to change them to pipes, however this:
/("(.*?)?,(.*?)")/gm
is only getting the first instance:
JSBIN
If callbacks are okay, you can go for something like this:
var str = '"test, test2, & test3",1324,,,,http://www.asdf.com';
var result = str.replace(/"[^"]+"/g, function (match) {
return match.replace(/,/g, '|');
});
console.log(result);
//"test| test2| & test3",1324,,,,http://www.asdf.com
This is very convoluted compared to regular expression version, however, I wanted to do this if just for the sake of experiment:
var PEG = require("pegjs");
var parser = PEG.buildParser(
["start = seq",
"delimited = d:[^,\"]* { return d; }",
"quoted = q:[^\"]* { return q; }",
"quote = q:[\"] { return q; }",
"comma = c:[,] { return ''; }",
"dseq = delimited comma dseq / delimited",
"string = quote dseq quote",
"seq = quoted string seq / quoted quote? quoted?"].join("\n")
);
function flatten(array) {
return (array instanceof Array) ?
[].concat.apply([], array.map(flatten)) :
array;
}
flatten(parser.parse('foo "bar,bur,ber" baz "bbbr" "blerh')).join("");
// 'foo "barburber" baz "bbbr" "blerh'
I don't advise you to do this in this particular case, but maybe it will create some interest :)
PS. pegjs can be found here: (I'm not an author and have no affiliation, I simply like PEG) http://pegjs.majda.cz/documentation

JavaScript - string regex backreferences

You can backreference like this in JavaScript:
var str = "123 $test 123";
str = str.replace(/(\$)([a-z]+)/gi, "$2");
This would (quite silly) replace "$test" with "test". But imagine I'd like to pass the resulting string of $2 into a function, which returns another value. I tried doing this, but instead of getting the string "test", I get "$2". Is there a way to achieve this?
// Instead of getting "$2" passed into somefunc, I want "test"
// (i.e. the result of the regex)
str = str.replace(/(\$)([a-z]+)/gi, somefunc("$2"));
Like this:
str.replace(regex, function(match, $1, $2, offset, original) { return someFunc($2); })
Pass a function as the second argument to replace:
str = str.replace(/(\$)([a-z]+)/gi, myReplace);
function myReplace(str, group1, group2) {
return "+" + group2 + "+";
}
This capability has been around since Javascript 1.3, according to mozilla.org.
Using ESNext, quite a dummy links replacer but just to show-case how it works :
let text = 'Visit http://lovecats.com/new-posts/ and https://lovedogs.com/best-dogs NOW !';
text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => {
// remove ending slash if there is one
link = link.replace(/\/?$/, '');
return `${link.substr(link.lastIndexOf('/') +1)}`;
});
document.body.innerHTML = text;
Note: Previous answer was missing some code. It's now fixed + example.
I needed something a bit more flexible for a regex replace to decode the unicode in my incoming JSON data:
var text = "some string with an encoded 's' in it";
text.replace(/&#(\d+);/g, function() {
return String.fromCharCode(arguments[1]);
});
// "some string with an encoded 's' in it"
If you would have a variable amount of backreferences then the argument count (and places) are also variable. The MDN Web Docs describe the follwing syntax for sepcifing a function as replacement argument:
function replacer(match[, p1[, p2[, p...]]], offset, string)
For instance, take these regular expressions:
var searches = [
'test([1-3]){1,3}', // 1 backreference
'([Ss]ome) ([A-z]+) chars', // 2 backreferences
'([Mm][a#]ny) ([Mm][0o]r[3e]) ([Ww][0o]rd[5s])' // 3 backreferences
];
for (var i in searches) {
"Some string chars and many m0re w0rds in this test123".replace(
new RegExp(
searches[i]
function(...args) {
var match = args[0];
var backrefs = args.slice(1, args.length - 2);
// will be: ['Some', 'string'], ['many', 'm0re', 'w0rds'], ['123']
var offset = args[args.length - 2];
var string = args[args.length - 1];
}
)
);
}
You can't use 'arguments' variable here because it's of type Arguments and no of type Array so it doesn't have a slice() method.

Categories

Resources