Replace everything between two strings with numbers i++ {0},{1} - javascript

Have mechanism that replaces strings like .NET string.Format in javascript ("{0} - {1}",'a','b') would result "a - b".
I am looking for mechanism that would Replace everything between two strings with {0}{1}...
Example :
var str = "([OrderDate] >= Func:{TheApplication().GetProfileAttr('TestDate')} ) and [OrderDate] < 1/1/2013 AND [Name] = Func:{TheApplication().GetProfileAttr('Name')}"
stringFormatProducer(str,"Func:{","}");
would give result
"([OrderDate] >= {0} ) and [OrderDate] < 1/1/2013 AND [Name] = {1}"
I have this mechanism done in horrid way where I am splitting it on Func:{ then } then iterating over it, I am sure someone already has a better solution.

var i = 0;
str.replace(/Func:{[^}]+}/g, function(c) {
return '{' + i++ + '}';
});
Or more flexible way:
var i = 0,
func = 'Func:';
str.replace(new RegExp(func + '{[^}]+}', 'g'), function(c) {
return '{' + i++ + '}';
});
A complete method for you:
String.prototype.createFormattingString = function(prefix, open, close) {
var re = new RegExp(prefix + open + '[^' + close + ']+' + close, 'g'),
i = 0;
return this.replace(re, function(c) {
return '{' + i++ + '}';
});
};
'(VAR > Func:{ some text })'.createFormattingString('Func:', '{', '}');
'(VAR > Func:[ some text ])'.createFormattingString('Func:', '\\[', '\\]');

Related

Replace middle of string given a range

Previous Question:
How replace an interval char in string:
For example Apple to A***e
Update:
Need get char positions 0-4 and -4 (Reverse)
var transaction = '1234567890987651907';
console.log('1234****1907');
Solution
var str = "01340946380001281972";
str.replace(/^(\d{0,4})(\d{4})(.*)/gi,"$1 **** $2");
I think you meant this
function maskIt(str, keep) {
var len = str.length,
re = new RegExp("(.{" + keep + "})(.{" + (len - keep * 2) + "})(.{" + keep + "})", "g")
console.log(re)
return str.replace(re, function(match, a, b, c) {
return a + ("" + b).replace(/./g, "*") + c
});
}
console.log(
maskIt("1234567890", 4),
maskIt("Apple", 1)
)
As a prototype:
String.prototype.maskIt = function(keep) { // don't use arrow or lose "this"
const re = new RegExp("(.{" + keep + "})(.{" + (this.length - keep * 2) + "})(.{" + keep + "})", "g");
return this.replace(re, (match, a, b, c) => a + ("" + b).replace(/./g, "*") + c);
}
console.log(
"1234567890".maskIt(4),
"Apple".maskIt(1)
)
Using slice
const maskIt = (str,keep) => {
return str.slice(0,keep)+Array.from({length: str.length-keep-1},() => '*').join('')+ str.slice(-keep)
}
console.log(
maskIt("1234567890",4),
maskIt("Apple",1)
)
Here is a solution using the base strings functions:
var input = "Apple";
var input_masked = input.substring(0, 1) + Array(input.length - 1).join("*") +
input.substring(input.length-1);
console.log(input_masked);
This approach is to sandwich the middle characters, masked as *, between the first and last character of the input.
Just replace the middle characters:
const str = "Apple";
const output = `${str[0]}${"*".repeat(str.length - 2)}${[...str].pop()}`;
console.log(output);
var str = "01340946380001281972";
str.replace(/^(\d{0,4})(\d{4})(.*)/gi,"$1 **** $2");

How can I split a string without losing the separator and without regex?

I have a string similar to "<p></p>". Now, I want to split this string, so I have 2 tags. If I do
var arr = "<p></p>".split("><") , I get an array that looks like
["<p", "/p>"]
Is there a simple way to keep the separator in this split? NOT a REGEX (Not a dupe) I want :
["<p>","</p>"]
Since javascript regex doesn't support look behind assertion it's not possible with String#split method. Use String#match method to get the complete string.
var arr = "<p></p>".match(/[\s\S]+?>(?=<|$)/g)
console.log(arr)
Without regex and using split you can do something like this.
var arr = "<p></p>".split('><').map(function(v, i, arr1) {
if (i != 0)
v = '<' + v;
if (i < arr1.length - 1)
v += '>';
return v;
})
// using ternary
var arr1 = "<p></p>".split('><').map(function(v, i, arr1) {
return (i != 0 ? '<' : '') + v + (i < arr1.length - 1 ? '>' : '');
})
console.log(arr);
console.log(arr1);
To do this without a regular expression, you'll need some kind of parser. Inspect every character, build up chunks and store them in an array. You may then want to process the bits, looking for tokens or doing other processing. E.g.
/* Break string into chunks of <...>, </...> and anything in between.
** #param {string} s - string to parse
** #returns {Array} chunks of string
*/
function getChunks(s) {
var parsed = [];
var limit = s.length - 1;
s.split('').reduce(function(buffer, char, i) {
var startTag = char == '<';
var endTag = char == '/';
var closeTag = char == '>';
if (startTag) {
if (buffer.length) {
parsed.push(buffer);
}
buffer = char;
} else if (endTag) {
buffer += char;
} else if (closeTag) {
parsed.push(buffer + char)
buffer = '';
} else {
buffer += char;
}
if (i == limit && buffer.length) {
parsed.push(buffer);
}
return buffer;
}, '');
return parsed;
}
['<p></p>',
'<div>More complex</div>',
'<span>broken tag</sp'
].forEach(function(s){
console.log(s + ' => [' + getChunks(s) + ']')
});
Note that this is very simple and just looks for <...> and </...> where ... can be anything.

Regex two string variables

Say I have two string variables:
a = 'LOVE';
b = '....';
How do I use regex (or whatever else is fastest) to combine a + b to make:
c = 'L.O.V.E.';
In my case, both strings are 4 characters long, always, and the second string is not a fixed character, I just made it a dot to make it look clearer on screen.
You can simply loop through the longer string and in each iteration append one character from both strings to your resulting string. I don't think you need any regular expression there:
a = 'LOVE';
b = '....';
var combinedString = '';
var largerLength = Math.max( a.length, b.length );
for( var i = 0; i < largerLength; i++ )
{
combinedString += a.charAt(i) + b.charAt(i);
}//for()
console.log( combinedString );
The above code will work for strings of any length. In case, you know beforehand that both strings are exactly 4 characters long, I think the fastest and most efficient way would be:
a = 'LOVE';
b = '....';
var combinedString = a.charAt[0] + b.charAt[0] + a.charAt[1] + b.charAt[1] + a.charAt[2] + b.charAt[2] + a.charAt[3] + b.charAt[3];
console.log( combinedString );
You could use Array#reduce for it
var a = 'LOVE',
b = '....';
c = a.split('').reduce(function (r, v, i) {
return r + v + b[i];
}, '');
console.log(c);
How to combine a + b via regex:
var a = "LOVE", b = "....";
var result = a.replace(/./g, (match, i) => match + b[i]);
console.log(result);
There is no need of regex for your problem. You can simply do it with the help of for loop
a = 'LOVE';
b = '....';
var result = '';
var length = Math.max( a.length, b.length );
for( var i = 0; i <+ length-1; i++ )
{
result = result + a.charAt(i);
result = result + b.charAt(i);
}
alert("Result of combined string is :"+ result);
You can use array functions on array likes (in this example strings) to iterate over it's items.
var a = 'LOVE',
b = '....',
c = Array.prototype.map
.call(a, (v, i) => v + b[i]).join('');
console.log(c);
If your second string is always composed of dots, instead of repeating same characters in string, try something like this:
Using Delimiter
var a = "LOVE";
var delimeter = ".";
var result = a.split("").join(delimeter) + delimeter;
console.log(result)
Array convert + manual concatenation
As an alternate to string.charAt, you can try something like this:
Note: you should do a1[i] || "" for cases where value can be undefined. Also you should use .toString() to avoid cases where both values are numeric and result will be addition instead of concatenation.
var a = 'LOVE';
var b = '....';
var c = ",,,,,,,,,,,";
function mergeStr(a, b) {
var a1 = a.split("");
var b1 = b.split("");
var len = Math.max(a.length, b.length)
var r = "";
for (var i = 0; i < len; i++) {
r += (a1[i] || "").toString() + (b1[i] || "").toString();
}
return r;
}
console.log(mergeStr(a,b))
console.log(mergeStr(a,c))

Replace last index of , with and in jQuery /JavaScript

i want to replace the last index of comma (,)in string with and.
eg . a,b,c with 'a,b and c'
eg q,w,e with q,w and e
DEMO
lastIndexOf finds the last index of the parameter string passed in it.
var x = 'a,b,c';
var pos = x.lastIndexOf(',');
x = x.substring(0,pos)+' and '+x.substring(pos+1);
console.log(x);
you can also use this function
function replace_last_comma_with_and(x) {
var pos = x.lastIndexOf(',');
return x.substring(0, pos) + ' and ' + x.substring(pos + 1);
}
console.log(replace_last_comma_with_and('a,b,c,d'));
An alternative solution using regex:
function replaceLastCommaWith(x, y) {
return x.replace(/,(?=[^,]*$)/, " " + y + " ");
}
console.log(replaceLastCommaWith("a,b,c,d", "and")); //a,b,c and d
console.log(replaceLastCommaWith("a,b,c,d", "or")); //a,b,c or d
This regex should do the job
"a,b,c,d".replace(/(.*),(.*)$/, "$1 and $2")
Try the following
var x= 'a,b,c,d';
x = x.replace(/,([^,]*)$/, " and $1");
Try
var str = 'a,b,c', replacement = ' and ';
str = str.replace(/,([^,]*)$/,replacement+'$1');
alert(str)
Fiddle Demo
A simple loop will help you out
first find the index of all , in your string using,
var str = "a,b,c,d,e";
var indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === ",") indices.push(i);
}
indices = [1,3,5,7] as it start from 0
len = indices.length()
str[indices[len - 1]] = '.'
This will solve your purpose.

Exempting characters in an escaped string

I have a little function that makes URL arguments out of an object:
function MkArgs(o) {
var ret = '?';
for (var i in o) {
ret += i + '=' + escape(o[i]) + '&';
}
return ret.substr(0, ret.length - 1);
}
which I then can call like this:
MkArgs({
protocol: 'wsfederation',
realm: 'https://www.x.com/',
fedRes: 'Home/FederationResult',
context: '~/Home/FAQ',
version: '1.0',
callback: '?'
});
to produce the following:
?protocol=wsfederation&realm=https%3A//www.x.com/&fedRes=Home/FederationResult&context=%7E/Home/FAQ&version=1.0&callback=%3F
everything is fine except that I don't want the last argument escaped i.e. I want:
callback=?
instead of
callback=%3F
is there any way I can indicate that within the string? I tried '\?' but that doesn't do it and haven't found any references as to how to protect a piece of string from escaping...
e
The MkArgs function is your own; change it to include an escape mechanism. I would advise against using backslash, though. If this is just your own code, perhaps it would be enough to put in a hackish special case.
That's a pretty special case. Maybe you should change your function:
function MkArgs(o, isJSONP) {
var ret = '?';
for (var i in o) {
var val = o[i];
val = escape(val);
ret += i + '=' + val + '&';
}
return ret.substr(0, ret.length - 1) + isJSONP ? '&callback=?':'';
}
and call it:
MkArgs({
protocol: 'wsfederation',
realm: 'https://www.x.com/',
fedRes: 'Home/FederationResult',
context: '~/Home/FAQ',
version: '1.0'
}, true);
The escape or encodeURIComponent functions don't have any way of "skipping" certain characters. So, all you can do is to either avoid calling the encode function when you don't want to or replace the chars you don't want encoded, call encode and then put the original chars back again.
If you want to skip escaping the whole value for a particular key, you can just check for the particular keys that you don't want to escape and handle appropriately like this:
function MkArgs(o) {
var ret = '?';
for (var i in o) {
var val = o[i];
if (i != "callback") {
val = encodeURIComponent(val);
}
ret += i + '=' + val + '&';
}
return ret.substr(0, ret.length - 1);
}
If you want to skip just certain characters, then you can replace them with some unique sequence, escape and then put them back:
function MkArgs(o) {
var ret = '?';
for (var i in o) {
var val = o[i];
if (i == "callback") {
val = val.replace(/\?/, "--xx--"); // replace with unique sequence
val = encodeURIComponent(val);
val = val.replace(/--xx--/, "?"); // put orig characters back
} else {
val = encodeURIComponent(val);
}
ret += i + '=' + val + '&';
}
return ret.substr(0, ret.length - 1);
}
FYI, note I've switched to using encodeURIComponent() which is recommended over the deprecated escape() because escape() doesn't work for non-ascii characters.
thanks everyone for the replies. what I ended up doing was:
function MkArgs(o) {
var ret = '?';
for (var i in o) {
ret += i;
if (o[i]) ret += '=' + escape(o[i]);
ret += '&';
}
return ret.substr(0, ret.length - 1);
}
then calling it like:
MkArgs({
protocol: 'wsfederation',
realm: 'https://www.x.com/',
fedRes: 'Home/FederationResult',
context: '~/Home/FAQ',
version: '1.0',
'callback=?': null
});
that way I don't rely on the values but the keys to make the distinction. not really pretty but it's the best I could think of
function MkArgs(o) {
var ret = '?';
var lastEl = '';
for (var i in o) {
ret += i + '=' + escape(o[i]) + '&';
lastEl = o[i];
}
return ret.substr(0, ret.length - 1 - lastEl.length) + lastEl;
}
this works for the last element in the object.
EDIT: It seems that in a classic for in loop, javascript does not have a precise order in which it loops over the object props, so the above solution is not guaranteed to work.
In this case you have 2 solutions :
If you know which property you want to "protect" from escaping, you should check for that prop in the loop and specifically not escape it :
for (var i in o) {
if(i=="myProp")
// unescape
else
// escape
}
If you do not now the property, but you want only the last one added into the query, you can do something like this (after building the query) :
var q = MkArgs(o);
var parts = q.split('=');
var toUnescape = parts[parts.length-1];
q = q.substring(0,q.length - toUnescape.length) + unescape(toUnescape);

Categories

Resources