- Replace all except first
- 10 Answers 10
- String.prototype.replaceAll()
- Try it
- Syntax
- Parameters
- Return value
- Exceptions
- Description
- How to replace all BUT the first occurrence of a pattern in string
- 6 Answers 6
- Remove all occurrences except last?
- Regex to replace everything except numbers and a decimal point
- 7 Answers 7
Replace all except first
Is it possible to replace all occurrences except the first one? So 123.45.67..89.0 should become 123.4567890 . Edit: I’m looking for a regex. I know how to do it with concat or using the index.
10 Answers 10
You could use a positive lookbehind to achieve this:
var str = "123.45.67.89.0"; var firstOccuranceIndex = str.search(/\./) + 1; // Index of first occurance of (.) var resultStr = str.substr(0, firstOccuranceIndex) + str.slice(firstOccuranceIndex).replace(/\./g, ''); // Splitting into two string and replacing all the dots (.'s) in the second string console.log(resultStr);
This is correct and it works. I think indexOf might be less expensive instead of search . I’m looking for a regex solution.
I know OP asks for solutions with regex, but for others here’s an alternative solution using String.prototype.split() and Array.prototype.reduce() :
function replaceAllExceptFirst(str, search, replace) < return str .split(search) .reduce((prev, curr, i) =>prev + (i == 1 ? search : replace) + curr); >
For this example, one would use this function like this:
replaceAllExceptFirst('123.45.67..89.0', '.', '')
In my case, I needed to replace all occurrences of a given substring except for the last one. For this, only a small modification is necessary:
function replaceAllExceptLast(str, search, replace) < return str .split(search) .reduce( (prev, curr, i, substrs) =>prev + (i !== substrs.length - 1 ? replace : search) + curr ); >
I am aware that using regex might be more efficient. Just thought that maybe this is easier to understand for folks like me who still can’t really wrap their head around regex.
PS: This is my first post on StackOverflow, so please be kind 🙂
String.prototype.replaceAll()
The replaceAll() method returns a new string with all matches of a pattern replaced by a replacement . The pattern can be a string or a RegExp , and the replacement can be a string or a function to be called for each match. The original string is left unchanged.
Try it
Syntax
replaceAll(pattern, replacement)
Parameters
Can be a string or an object with a Symbol.replace method — the typical example being a regular expression. Any value that doesn’t have the Symbol.replace method will be coerced to a string.
If pattern is a regex, then it must have the global ( g ) flag set, or a TypeError is thrown.
Can be a string or a function. The replacement has the same semantics as that of String.prototype.replace() .
Return value
A new string, with all matches of a pattern replaced by a replacement.
Exceptions
Thrown if the pattern is a regex that does not have the global ( g ) flag set (its flags property does not contain «g» ).
Description
This method does not mutate the string value it’s called on. It returns a new string.
Unlike replace() , this method would replace all occurrences of a string, not just the first one. This is especially useful if the string is not statically known, as calling the RegExp() constructor without escaping special characters may unintentionally change its semantics.
function unsafeRedactName(text, name) return text.replace(new RegExp(name, "g"), "[REDACTED]"); > function safeRedactName(text, name) return text.replaceAll(name, "[REDACTED]"); > const report = "A hacker called ha.*er used special characters in their name to breach the system."; console.log(unsafeRedactName(report, "ha.*er")); // "A [REDACTED]s in their name to breach the system." console.log(safeRedactName(report, "ha.*er")); // "A hacker called [REDACTED] used special characters in their name to breach the system."
If pattern is an object with a Symbol.replace method (including RegExp objects), that method is called with the target string and replacement as arguments. Its return value becomes the return value of replaceAll() . In this case the behavior of replaceAll() is entirely encoded by the @@replace method, and therefore will have the same result as replace() (apart from the extra input validation that the regex is global).
If the pattern is an empty string, the replacement will be inserted in between every UTF-16 code unit, similar to split() behavior.
For more information about how regex properties (especially the sticky flag) interact with replaceAll() , see RegExp.prototype[@@replace]() .
How to replace all BUT the first occurrence of a pattern in string
quick question: my pattern is an svg string and it looks like l 5 0 l 0 10 l -5 0 l 0 -10 To do some unittest comparison against a reference I need to ditch all but the first l I know i can ditch them all and put an ‘l’ upfront, or I can use substrings. But I’m wondering is there a javascript regexp idiom for this?
i know you said you don’t want this, but substring up to the first space seems like the easiest to read and maintain.
@Randy yes I know, but I wanted to deepen my knowledge on regexps. Your point about readability and maintainability is something to consider. I’ll start with commenting.
6 Answers 6
You can try a negative lookahead, avoiding the start of the string:
I’m trying to modify this to work for the first ‘-‘ character that appears, and I’m having a very difficult time of it :(. Any help is appreciated. Thanks in advance.
@GrantRobertSmith I know this is way late, but I provided an answer that covers what I think you’re looking for.
There’s no JS RegExp to replace everything-but-the-first-pattern-match. You can, however, implement this behaviour by passing a function as a second argument to the replace method.
var regexp = /(foo bar )(red)/g; //Example var string = "somethingfoo bar red foo bar red red pink foo bar red red"; var first = true; //The arguments of the function are similar to $0 $1 $2 $3 etc var fn_replaceBy = function(match, group1, group2) < //group in accordance with RE if (first) < first = false; return match; >// Else, deal with RegExp, for example: return group1 + group2.toUpperCase(); > string = string.replace(regexp, fn_replaceBy); //equals string = "something foo bar red foo bar RED red pink foo bar RED red"
The function ( fn_replaceBy ) is executed for each match. At the first match, the function immediately returns with the matched string (nothing happens), and a flag is set.
Every other match will be replaced according to the logic as described in the function: Normally, you use $0 $1 $2 , et cetera, to refer back to groups. In fn_replaceBy , the function arguments equal these: First argument = $0 , second argument = $1 , et cetera.
The matched substring will be replaced by the return value of function fn_replaceBy . Using a function as a second parameter for replace allows very powerful applcations, such as an intelligent HTML parser.
Remove all occurrences except last?
This should be the accepted answer. To say this in English, the regex says «match all occurrences of . that have another . after them», then you simply replace with an empty string. You’ll hear occasional complaints that regex aren’t as readable as doing a big split then formatting from the array, but it’s pretty easy to simply describe your regex in a comment above it.
I don’t think it’s wise to put too much stock in isolated performance tests that the engine won’t be as smart about optimising, but the positive lookahead doesn’t seem to scale as nicely. Here I found it’s quite a bit faster for short strings (the ‘1.2.3.4’ example) vs splitting the array, but lags way behind on longer strings: jsperf.com/removing-all-but-last-string-token
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)
> 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:
(If your string contains newlines, you will have to use [.\n] rather than naked . s)
just for info: if someone needs to remove all but first then use >>> function removeAllButFirst(string, token) < var parts = string.split(token); return parts.slice(0,1) + token + parts.slice(1).join(''); >
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);
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.
Regex to replace everything except numbers and a decimal point
I have a text field that needs to remain only text or decimal. Here is the code that I’m currently using to replace everything except numbers and a decimal point. Issue is, I can’t figure out a regex that will identify everything else
document.getElementById(target).value = newVal.replace(/\D[^\.]/g, "");
The \D works fine, but I’ve tried (. ), (?!\.), [^.], [^\.] and so on. Any suggestions for a regular expression that identifies positively with anything except a number or a decimal? Thanks for the help
in case you’re looking to check for actual numbers rather than numeric digits: stackoverflow.com/questions/42328875/…
7 Answers 7
document.getElementById(target).value = newVal.replace(/[^0-9.]/g, '');
@Hugo this does not allow anything, you should just not pass a string that could potentially contain more decimal points and pre-process it first. It’s like saying string allows every character.
Then run the returned value through parseFloat. That will remove additional decimal points. e.g. parseFloat(«46554.4655465.54654.545345.5») = 46554.4655465
Moshen, replace(/[^0-9.\-]/g, ») is a good start, but allows subtraction formulas, such as -7-8, which will break data systems without server side checking. The regex must only match the first character for negation. I will not post the solution on SO because the last regex question and answer I posted was deleted by Sammitch, who, like the new owners of SO, don’t understand how SO works (posting questions and answers together), and don’t know the definition of the word blog (it’s web-log). So I don’t cast my pearls before swine: let the folks who use SO break their data systems.