Edit
sorry if the question wasn't clear
here is the question..
create your version of javascript split function,
you may use indexOf and substring to help.
so if i give you a string "heellloolllloolllo" and i want to remove "llll" the function should return "heellloooolllo"
This what I did so far:
function split() {
var entered_string = document.forms["form1"]["str"].value;
var deleted_char = document.forms["form1"]["char"].value;
var index = entered_string.indexOf(deleted_char);
var i = deleted_char.length;
var result;
var x ;
for (x = 0; x< entered_string.length; x++ )
{
if (index < 0) {
result = entered_string;
} else {
result = entered_string.substring(0, index) +entered_string.substring(index+i);
}
}
alert(result)
}
Use the replace() function with the g at the end of your regular expression. It's called a "global modifier".
var string = 'heellloolllloolllo';
var res = string.replace(/llll/g, '');
console.log(res)
If your substring is a variable then you need to construct a new Regex object and set the g as the second parameter.
var string = 'heellloolllloolllo';
var find = 'llll';
var regex = new RegExp(find,'g');
var res = string.replace(regex, '');
console.log(res)
There are other useful modifiers you can use:
g - Global replace. Replace all instances of the matched string in the provided text.
i - Case insensitive replace. Replace all instances of the matched string, ignoring differences in case.
m - Multi-line replace. The regular expression should be tested for matches over multiple lines.
See this post for more information, credit to #codejoe.
Using String#replace and RegExp (the clean way)
var str = 'llllheellloolllloolllollll';
var matchStr = 'llll';
function removeSubString(str, matchStr) {
var re = new RegExp(matchStr, 'g');
return str.replace(re,"");
}
console.log(removeSubString(str, matchStr));
Using String#indexOf and String#substring
var str = 'llllheellloolllloolllollll';
var matchStr = 'llll';
function removeSubString(str, matchStr) {
var index = str.indexOf(matchStr);
while(index != -1) {
var firstSubStr = str.substring(0, index);
var lastSubStr = str.substring(index + matchStr.length);
str = firstSubStr + lastSubStr;
index = str.indexOf(matchStr);
}
return str;
}
console.log(removeSubString(str,matchStr))
Related
In my JavaScript code I have a regular expression with capture groups (that is configured by library user) and a source string which matches this regular expression. The regular expression matches whole string (i.e. it has ^ and $ characters at its start and end).
A silly example:
var regex = /^([a-zA-Z]{2})-([0-9]{3})_.*$/;
var sourceStr = "ab-123_foo";
I want to reassemble the source string, replacing values in the capture groups and leaving the rest of the string intact. Note that, while this example has most of the "rest of the string" at its end, it actually may be anywhere else.
For example:
var replacements = [ "ZX", "321" ];
var expectedString = "ZX-321_foo";
Is there a way to do this in JavaScript?
NB: The regular expression is configured by the library user via the legacy API. I can not ask user to provide a second regular expression to solve this problem.
Without changing the regex the best I can think of is a callback that replaces the matches
sourceStr = sourceStr.replace(regex, function(match, $1, $2, offset, str) {
return str.replace($1, replacements[0]).replace($2, replacements[1]);
});
That's not a very good solution, as it would fail on something like
var sourceStr = "ab_ab-123_foo";
as it would replace the first ab instead of the matched one etc. but works for the given example and any string that doesn't repeat the matched characters
var regex = /^([a-zA-Z]{2})-([0-9]{3})_.*$/;
var sourceStr = "ab-123_foo";
var replacements = [ "ZX", "321" ];
sourceStr = sourceStr.replace(regex, function(match, $1, $2, offset, str) {
return str.replace($1, replacements[0]).replace($2, replacements[1]);
});
document.body.innerHTML = sourceStr;
I think this is close. It satisfies the two test cases but I'm unsure about leading and trailing groupings.
function replacer (regex, sourceStr, replacements) {
// Make a new regex that adds groups to ungrouped items.
var groupAll = "";
var lastIndex = 0;
var src = regex.source;
var reGroup=/\(.*?\)/g;
var match;
while(match = reGroup.exec(src)){
groupAll += "(" + src.substring(lastIndex, match.index) + ")";
groupAll += match[0];
lastIndex = match.index + match[0].length;
}
var reGroupAll = new RegExp(groupAll);
// Replace the original groupings with the replacements
// and append what was previously ungrouped.
var rep = sourceStr.replace(reGroupAll, function(){
// (match, $1, $2, ..., index, source)
var len = arguments.length - 2;
var ret = "";
for (var i = 1,j=0; i < len; i+=2,j++) {
ret += arguments[i];
ret += replacements[j];
}
return ret;
});
return rep;
}
var regex = /^([a-zA-Z]{2})-([0-9]{3})_.*$/;
var sourceStr = "ab-123_foo";
var replacements = [ "ZX", "321" ];
var expectedString = "ZX-321_foo";
var replaced = replacer(regex, sourceStr, replacements);
console.log(replaced);
console.log(replaced === expectedString);
regex = /^.*_([a-zA-Z]{2})-([0-9]{3})$/;
sourceStr = "ab_ab-123";
expectedString = "ab_ZX-321";
var replaced = replacer(regex, sourceStr, replacements);
console.log(replaced);
console.log(replaced === expectedString);
Output:
ZX-321_foo
true
ab_ZX-321
true
Is there a javascript string function that search a regex and it will start the search at the end?
If not, what is the fastest and/or cleanest way to search the index of a regex starting from the end?
example of regex:
/<\/?([a-z][a-z0-9]*)\b[^>]*>?/gi
Maybe this can be useful and easier:
str.lastIndexOf(str.match(<your_regex_here>).pop());
Perhaps something like this is suitable for you?
Javascript
function lastIndexOfRx(string, regex) {
var match = string.match(regex);
return match ? string.lastIndexOf(match.slice(-1)) : -1;
}
var rx = /<\/?([a-z][a-z0-9]*)\b[^>]*>?/gi;
console.log(lastIndexOfRx("", rx));
console.log(lastIndexOfRx("<i>it</i><b>bo</b>", rx));
jsFiddle
And just for interest, this function vs the function that you choose to go with. jsperf
This requires that you format your regex correctly for matching exactly the pattern you want and globally (like given in your question), for example /.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i will not work with this function. But what you do get is a function that is clean and fast.
You may create a reverse function like:
function reverse (s) {
var o = '';
for (var i = s.length - 1; i >= 0; i--)
o += s[i];
return o;
}
and then use
var yourString = reverse("Your string goes here");
var regex = new Regex(your_expression);
var result = yourString.match(regex);
Another idea: if you want to search by word in reverse order then
function reverseWord(s) {
var o = '';
var split = s.split(' ');
for (var i = split.length - 1; i >= 0; i--)
o += split[i] + ' ';
return o;
}
var yourString = reverseWord("Your string goes here");
var regex = new Regex(your_expression);
var result = yourString.match(regex);
Andreas gave this from the comment:
https://stackoverflow.com/a/274094/402037
String.prototype.regexLastIndexOf = function(regex, startpos) {
regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
if(typeof (startpos) == "undefined") {
startpos = this.length;
} else if(startpos < 0) {
startpos = 0;
}
var stringToWorkWith = this.substring(0, startpos + 1);
var lastIndexOf = -1;
var nextStop = 0;
while((result = regex.exec(stringToWorkWith)) != null) {
lastIndexOf = result.index;
regex.lastIndex = ++nextStop;
}
return lastIndexOf;
}
Which gives the functionality that I need, I tested my regex, and it is successful. So I'll use this
It depends what you exactly want to search for. You can use string.lastIndexOf or inside the regexp to use $ (end of the string).
Update:
try the regexp
/<\/?([a-z][a-z0-9]*)\b[^>]*>?[\w\W]*$/gi
var m = text.match(/.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i);
if (m) {
textFound = m[1];
position = text.lastIndexOf(textFound);
}
Use .* to skip as much text as posible, capture the text found and search it with lastIndexOf
EDIT:
Well, if text is found, no need to search with lastIndexOf. m[0] contains the full coincidence (including all the initial padding), and m[1] the searched text. So position of found text is m[0].length - m[1].length
var m = text.match(/.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i);
if (m) {
textFound = m[1];
position = m[0].length - m[1].length;
}
Assuming you're looking for a string 'token', then you need the position of 'token' that has no other 'token' following until the end of the string.
So you should compose your regex something like that:
$token = 'token';
$re = "/(?:$token)[^(?:$token)]*$/";
This will find your 'token' where no further 'token' can be found until string end. The "(?:" grouping simply makes the group non-storing, slightly speeding up performance and saving memory.
I must have a syntax error in my code but I can't see it. fiddle here
var comma = ',,';
var stop = '.。';
var expression = '/[]+/';
expression = expression.substr(0,2) + comma + stop + expression.substr(2);
expression = new RegExp(expression,'g');
var res = "foo,吧。baz".split(expression);
for ( var n=0; n < res.length; n++ ) {
}
I'm expecting res.length to be 3 but it is always 1 and returns the full string. What am I missing?
/ is used as delimiter for RegExp literal. e.g. /[a-zA-Z]/g
/ is not needed when you pass a pattern to the RegExp constructor. e.g. new RegExp('[a-zA-Z]', 'g')
To resolve the problem, remove the / (and modify the rest of your code):
var expression = '[]+';
Or you can just pass a RegExp literal directly:
var res = "foo,吧。baz".split(/[,,.。]+/g);
When you creat your Regex you're using this: var expression = '/[]+/';. The / delimiters are for use when you're delaring a regex like this:
var expression = /[]+/; // note: no quotes.
You're using new Regexp(), so they're not required in your string. Removing them gives this:
var comma = ',,';
var stop = '.。';
var expression = '[]+';
expression = expression.substr(0,1) + comma + stop + expression.substr(1);
expression = new RegExp(expression,'g');
var res = "foo,吧。baz".split(expression);
for ( var n=0; n < res.length; n++ ) {
var item = document.createElement('li');
item.innerHTML = res[n];
document.getElementById('list').appendChild( item );
}
Which does what you expect. See this fiddle. I've adjusted the string indices and the loop index so that things work...
var expression = '/[]+/';
Should be
var expression = '[]+';
Also, adjust the substring indices accordingly
http://jsfiddle.net/2Pbm3/4/
Working like this :
var comma = ',,';
var stop = '.。';
var expression = '[]+';
expression = expression.substr(0,1) + comma + stop + expression.substr(1);
expression = new RegExp(expression,'g');
var res = "foo,吧。baz".split(expression);
for ( var n=0; n < res.length; n++ ) {
var item = document.createElement('li');
item.innerHTML = res[n];
document.getElementById('list').appendChild( item );
}
Here's a thing i've been trying to resolve...
We've got some data from an ajax call and the result data is between other stuff a huge string with key:value data. For example:
"2R=OK|2M=2 row(s) found|V1=1,2|"
Is it posible for js to do something like:
var value = someFunction(str, param);
so if i search for "V1" parameter it will return "1,2"
I got this running on Sql server no sweat, but i'm struggling with js to parse the string.
So far i'm able to do this by a VERY rudimentary for loop like this:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
var arr = str.split("|");
var i = 0;
var value = "";
for(i = 0; i<arr.length; ++i){
if( arr[i].indexOf(param)>-1 ){
value = arr[i].split("=")[1];
}
}
console.log(value);
if i put that into a function it works, but i wonder if there's a more efficient way to do it, maybe some regex? but i suck at it. Hopefully somebody may shine a light on this for me?
Thanks!
This seems to work for your specific use-case:
function getValueByKey(haystack, needle) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp(needle + '=(.+)');
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1');
console.log(test);
JS Fiddle demo.
And, to include the separator in your search (in order to prevent somethingElseV1 matching for V1):
function getValueByKey(haystack, needle, separator) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp('\\' + separator + needle + '=(.+)\\' + separator);
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1', '|');
console.log(test);
JS Fiddle demo.
Note that this approach does require the use of the new RegExp() constructor (rather than creating a regex-literal using /.../) in order to pass variables into the regular expression.
Similarly, because we're using a string to create the regular expression within the constructor, we need to double-escape characters that require escaping (escaping first within the string and then escaping within in the created RegExp).
References:
RegExp.
String.match().
This should work for you and it's delimiters are configurable (if you wish to parse a similar string with different delimiters, you can just pass in the delimiters as arguments):
var parseKeyValue = (function(){
return function(str, search, keyDelim, valueDelim){
keyDelim = quote(keyDelim || '|');
valueDelim = quote(valueDelim || '=');
var regexp = new RegExp('(?:^|' + keyDelim + ')' + quote(search) + valueDelim + '(.*?)(?:' + keyDelim + '|$)');
var result = regexp.exec(str);
if(result && result.length > 1)
return result[1];
};
function quote(str){
return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
}
})();
Quote function borrowed form this answer
Usage examples:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
parseKeyValue(str, param); // "1,2"
var str = "2R=OK&2M=2 row(s) found&V1=1,2";
var param = "2R";
parseKeyValue(str, param, '&'); // "OK"
var str =
"2R=>OK\n\
2M->2 row(s) found\n\
V1->1,2";
var param = "2M";
parseKeyValue(str, param, '\n', '->'); // "2 row(s) found"
Here is another approach:
HTML:
<div id="2R"></div>
<div id="2M"></div>
<div id="V1"></div>
Javascript:
function createDictionary(input) {
var splittedInput = input.split(/[=|]/),
kvpCount = Math.floor(splittedInput.length / 2),
i, key, value,
dictionary = {};
for (i = 0; i < kvpCount; i += 1) {
key = splittedInput[i * 2];
value = splittedInput[i * 2 + 1];
dictionary[key] = value;
}
return dictionary;
}
var input = "2R=OK|2M=2 row(s) found|V1=1,2|",
dictionary = createDictionary(input),
div2R = document.getElementById("2R"),
div2M = document.getElementById("2M"),
divV1 = document.getElementById("V1");
div2R.innerHTML = dictionary["2R"];
div2M.innerHTML = dictionary["2M"];
divV1.innerHTML = dictionary["V1"];
Result:
OK
2 row(s) found
1,2
I want to remove all occurrences of substring = . in a string except the last one.
E.G:
1.2.3.4
should become:
123.4
You can use regex with positive look ahead,
"1.2.3.4".replace(/[.](?=.*[.])/g, "");
2-liner:
function removeAllButLast(string, token) {
/* Requires STRING not contain TOKEN */
var parts = string.split(token);
return parts.slice(0,-1).join('') + token + parts.slice(-1)
}
Alternative version without the requirement on the string argument:
function removeAllButLast(string, token) {
var parts = string.split(token);
if (parts[1]===undefined)
return string;
else
return parts.slice(0,-1).join('') + token + parts.slice(-1)
}
Demo:
> removeAllButLast('a.b.c.d', '.')
"abc.d"
The following one-liner is a regular expression that takes advantage of the fact that the * character is greedy, and that replace will leave the string alone if no match is found. It works by matching [longest string including dots][dot] and leaving [rest of string], and if a match is found it strips all '.'s from it:
'a.b.c.d'.replace(/(.*)\./, x => x.replace(/\./g,'')+'.')
(If your string contains newlines, you will have to use [.\n] rather than naked .s)
You can do something like this:
var str = '1.2.3.4';
var last = str.lastIndexOf('.');
var butLast = str.substring(0, last).replace(/\./g, '');
var res = butLast + str.substring(last);
Live example:
http://jsfiddle.net/qwjaW/
You could take a positive lookahead (for keeping the last dot, if any) and replace the first coming dots.
var string = '1.2.3.4';
console.log(string.replace(/\.(?=.*\.)/g, ''));
A replaceAllButLast function is more useful than a removeAllButLast function. When you want to remove just replace with an empty string:
function replaceAllButLast(str, pOld, pNew) {
var parts = str.split(pOld)
if (parts.length === 1) return str
return parts.slice(0, -1).join(pNew) + pOld + parts.slice(-1)
}
var test = 'hello there hello there hello there'
test = replaceAllButLast(test, ' there', '')
console.log(test) // hello hello hello there
Found a much better way of doing this. Here is replaceAllButLast and appendAllButLast as they should be done. The latter does a replace whilst preserving the original match. To remove, just replace with an empty string.
var str = "hello there hello there hello there"
function replaceAllButLast(str, regex, replace) {
var reg = new RegExp(regex, 'g')
return str.replace(reg, function(match, offset, str) {
var follow = str.slice(offset);
var isLast = follow.match(reg).length == 1;
return (isLast) ? match : replace
})
}
function appendAllButLast(str, regex, append) {
var reg = new RegExp(regex, 'g')
return str.replace(reg, function(match, offset, str) {
var follow = str.slice(offset);
var isLast = follow.match(reg).length == 1;
return (isLast) ? match : match + append
})
}
var replaced = replaceAllButLast(str, / there/, ' world')
console.log(replaced)
var appended = appendAllButLast(str, / there/, ' fred')
console.log(appended)
Thanks to #leaf for these masterpieces which he gave here.
You could reverse the string, remove all occurrences of substring except the first, and reverse it again to get what you want.
function formatString() {
var arr = ('1.2.3.4').split('.');
var arrLen = arr.length-1;
var outputString = '.' + arr[arrLen];
for (var i=arr.length-2; i >= 0; i--) {
outputString = arr[i]+outputString;
}
alert(outputString);
}
See it in action here: http://jsbin.com/izebay
var s='1.2.3.4';
s=s.split('.');
s.splice(s.length-1,0,'.');
s.join('');
123.4