How do I use the Javascript string replace method? I don't know much about regular expressisons, but I can seem to get is sort of working without them?
There is no single question here. The above question is just one of MANY questions that I get from a lot of people about using the Javascript replace method that is built into the Javascript String object. The following should hopefully address all of their questions at one time.
First, we have to create a little text blurb on which to perform our Javascript string replace testing.
Launch code in new window » Download code as text file »
When doing a simple string replace, only the first instance of the matching string will be replaced.
Launch code in new window » Download code as text file »
If you want to replace more than the first instance, you can start looping over the string making replacements until the target string can no longer be found in the string value.
Launch code in new window » Download code as text file »
Notice that the replace method is CASE SENSITIVE. It went through and replaced out all of the "th" instances, but did not replace anything with an upper case T (ex. The). Looping over the indexes is a bit of pain in the butt. If you are intending to do this type of operation a lot, you might want to consider building a replaceAll() method into the Javascript String object as a prototype method so that it would be available to all strings.
Launch code in new window » Download code as text file »
Now, replaceAll() is a built in method for all string values. Try performing the same replace we did above, but use this built in method instead.
Launch code in new window » Download code as text file »
You will see that it does the same replace with much less code! Not only that, every string value in you application can leverage the replaceAll() method once the prototype has been defined.
As you saw above though, the replace is still case sensitive. If you wanted to build a case INSENSITIVE replace, you could do so using a modification of the logic above. But, this would get very hairy very fast. Instead, you can use a regular expression (often referred to as a RegEx or a RegExp). Regular expressions are much more powerful than standard string matching as they can use very complicated logic.
Launch code in new window » Download code as text file »
As you can see, we have the same replace happening. So let's take a look at what's going on. Instead of passing simple target string to the replace() method, we are passing in a regular expression (new RegExp()) object instance. The RegExp() takes two arguments, the expression and the search flags (left blank in our example). There are two universally valid flags: [g] which means globally replace and [i] which
means case INsensitive. By default, the regular expression is NOT global and case sensitive.
Launch code in new window » Download code as text file »
We just did a global replace in ONE line of code. Compare this to the non-regular expression solution which takes 13 lines of code (I am including line breaks and white space in the count). Now for the magic... let's do that same thing with out case sensitivity.
Launch code in new window » Download code as text file »
We just replaced out that additional "Th" simply by adding the flag [i] into the regular expression. That's how powerful regular expressions are. But there's more. Regular expressions are more than just flags. Much more!
Image that for some reason, you knew about regular expressions, but you didn't know about the case insensitive flag [i]. You could have performed the same replace using this:
Launch code in new window » Download code as text file »
This groups the two letters together, and for each letter it tells the replacing algorithm to match t OR T followed by h OR H. There is sooo much more that regular expressions can do. Unfortunately, that is outside the scope of this entry. You should really look into regular expression both in Javascript and in ColdFusion / Java. They are amazing.
But what happens if you don't want to do a simple replace? The replace method allows some very interesting flexibility. Up until now, we have been passing a simple string in a the "replace-in" argument ([X]). But, you don't have to. You can pass in a function pointer instead.
For this example, let's replace out the target string with a random letter in the brackets, not necessarily the X. First we have to create a function that will return the resultant random string.
Launch code in new window » Download code as text file »
Try calling the function on its own a few times, just to see how it behaves.
Launch code in new window » Download code as text file »
As you can see, it randomly (as random as possible) picks a letter to return. Now, let's call the replace with the RandomString() method sent as the second argument. We will do this a few times so you can see the randomness in effect.
Launch code in new window » Download code as text file »
Notice that we are passing in a POINTER to the function but not actually calling it. RandomString vs. RandomString(). There's one thing I did not mention yet. Not only can you pass in a function as an argument, but when the replace method is taking place, it passes in the target match as an argument to this function. We could have re-written the function as such:
Launch code in new window » Download code as text file »
Now, we will run it again, just once, so you can see it in action.
Launch code in new window » Download code as text file »
Notice now that the replace string is the form of [th : X]. That is pretty cool, but it gets even cooler. This same methodology applies to doing replacements using regular expressions (didn't you have a hunch we'd see them again).
Just to kick of this demo, I will run the global regular expression replace to show that it works the same way.
Launch code in new window » Download code as text file »
Notice that we have now replaced all [g] the case insensitive [i] substring matches with the random letter.
This is very cool, but regular expressions take this even one step further. You can group parts of a regular expression and each group will get passed as an argument to the function method. In this example, let's group each letter and have them passed as an argument.
Launch code in new window » Download code as text file »
The one caveat here, that is different from the standard string replace method is that when using regular expressions, the first argument passed into the function, like the string replace, is the entire matching string.
Now, let's run it with groups in the regular expression. Groups are denoted by () around parts of the expression. Let's run a global, case insensitive match for a maximum amount of fun :)
Launch code in new window » Download code as text file »
Notice that all the instances of "th" were replaced with the case-appropriate "[t][h]"
So now that we have seen the technicals of the Javascript string replace method, let's explore some ways that we can leverage the replace method to do non-replace actions. For example, we can use the Javascript string replace method to COUNT the number of times a string appears in the given string.
Launch code in new window » Download code as text file »
Alert the count of the reg expression.
Launch code in new window » Download code as text file »
You might be confused by the nested functions in the example above. Since the function being passed to the replace method is a nested function, Javascript will search the local variable scope for "intCount." When it cannot find it, it will move up the scope chain to the CountValue() function which does contain a variable intCount. This is the variable that will be updated for each iteration of the loop.
One last example that seems to stump a lot of people is the replacing of strings that span multiple lines. In our sample text, the line break "\n" is what creates several lines that we can try to match across. The trick is just to treat the "\n" as just another character.
For this example, we will replace the character "s" that ends a word, followed by any white space, until the end of the next word.
Launch code in new window » Download code as text file »
As you can see, the matches were made across the line break with no problem at all. By treating the "\n" as just another character that might come up and be matched on, there is no problems to worry about. In our example, the clause "[^ ]" will match on any character that is NOT a space character. This includes alpha-numeric characters, punctuation, and even the new line character.
One caveat to remember is that while in ColdFusion, new lines that come out of a textarea are represented by the character 13 followed by 10, once inside a Javascript string, the new line is JUST "\n".
Well, that's the short and skinny of Javascript String replacement tips and tricks. I am sure you are beginning to see just how crazy awesome they can be. And, if you don't know your regular expressions, I hope that this little tutorial has piqued your interests. They will change your life.
Download Code Snippet ZIP File
Comments (37) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
There are a LOT of scripts out there that use replace() assuming it'll do a global replace without using a regex (and yes, they're all broken). Nice to find a full and detailed description, thanks :).
Posted by Excellent summary, thanks. on Aug 23, 2006 at 12:28 AM
No problem my man, always glad to help. Javascript rules, and RegExp is wicked sweet.
Posted by Ben Nadel on Aug 23, 2006 at 3:21 PM
try this , for replacing more than one charachter
<script>
test="kuut";
test = test.replace(/u/g, 'a' );
alert(test);
</script>
or for \n:
var test = text.replace(/\n/g, '<br>');
Posted by Marieke on Oct 4, 2006 at 8:59 AM
I just want to thank you for your article on string replacement methods. It was just so cool. Thanks a million times.
Posted by Toan Nguyen on Oct 20, 2006 at 5:50 PM
How about an option to replace whole words only? Thanks.
Posted by Toan Nguyen on Oct 20, 2006 at 6:02 PM
Toan,
Glad to help! Javascript is an awesome, powerful language. Getting whole words is a bit of sticky matter. You can't quite use the word boundry "\b" because that won't match on punctuation. For instance, in the word "can't", the expression \b\w+\b would match "can" since "'" is a non-word character.
If you know the set of data you have conforms to a certain format (ie. NOT having punctuation, then you can use the \b (and I think \A and \Z). If you are gonna use punctuation, things just get harder.
Hope that helps a bit and not confuses you more.
Posted by Ben Nadel on Oct 20, 2006 at 6:15 PM
Stumbled across your site searching Google. Great examples. I really liked the example of extending the String object to make the replaceAll method available globally. There is one change I would make which is to do a quick check to insure you don't get caught in an endless loop:
if(strTarget != strSubString) {
while loop etc...
}
Posted by Jared Fine on Dec 15, 2006 at 9:35 AM
Jared,
Thanks for enjoying the site and the examples. I am not sure how you would get caught in an endless loop. However, nothing wrong with checking for equality right up front so that you don't have to do any extra parsing.
Posted by Ben Nadel on Dec 15, 2006 at 1:07 PM
split.join works much more predictable.
Posted by GEV on Dec 26, 2006 at 10:16 PM
::cool work::
Posted by Rajakuamr on Jan 11, 2007 at 1:41 AM
::cool work::
Posted by Rajakuamr on Jan 11, 2007 at 1:41 AM
::cool work::
Posted by Rajakuamr on Jan 11, 2007 at 1:47 AM
great article...i was just wondering how you would do a replace with a regex for "(h)"
how would you define a regex replacing the exact match of those 3 characters with say [X]?
so yesyeyses(h)sdgfsd(h)
would become:
so yesyeyses[X]sdgfsd[X]
thx!
Posted by Peter on Jan 12, 2007 at 8:38 AM
wow , great guide
Posted by Vishal Arya on Mar 6, 2007 at 7:16 AM
my FF javascript console says:
replaceAll is not a function
Posted by carsten on Mar 15, 2007 at 11:23 AM
oh, I see, the other script should be included.
thanks!
Posted by Carsten on Mar 15, 2007 at 11:26 AM
can you use this to replace an image? For example, I am using a 3rd party host software that allows some customizations but none directly to the code. It does let you insert your own header code to add to your pages. The software uses a default image that I want to replace with my own default image and I'm wondering if I can do that using a variation of this javascript. So basically I'd want to replace any instances of www.theirsite.com/theirimage.jpg with www.mysite.com/myimage.jpg.
Possible?
Posted by bons on Mar 23, 2007 at 10:20 PM
@Bons,
You can certainly do something like that. I have not tested this, but something like:
for (var i = 0 ; i < document.images.length ; i++){
if (document.images[ i ].src.match( new RegExp( "www\.theirsite\.com/theirimage\.jpg', "i" ))){
document.images[ i ].src = document.images[ i ].src = "www.mysite.com/myimage.jpg";
}
This actually would not really call for a RegEx. But, depending on your rules, it might.
Posted by Ben Nadel on Mar 23, 2007 at 11:26 PM
there's no need to create a RegExp object inside replace function, as the latter supports regular expressions itself, e.g.:
str.replace(/<br>/gi,"\n");
where gi obviously stends for global search + case insensitive.
same applies for match(), search() and the like.
Posted by someone on Apr 28, 2007 at 10:39 AM
While that is true, I find it much less readable. Using new RegExp() allows me to slightly break up the code and let me read it more easily. It just personal.
Posted by Ben Nadel on Apr 28, 2007 at 12:19 PM
It was nice article I have read on javascript. The presentation was wonderful. It was quite useful for me and it also showed the power of regular expression in javascript.
Thanks.
Posted by Sarat Chandra Sekhar on Jul 17, 2007 at 4:06 PM
THANK YOU! FINALLY someone who can explain things clearly and simply....
Posted by Teresa on Aug 22, 2007 at 11:49 AM
@Teresa,
Glad to help. If you ever get stumped on something and want a demo / tutorial / explanation, just let me know.
Posted by Ben Nadel on Aug 22, 2007 at 12:31 PM
Hi Ben,
This was a true lesson in string manipulation for me, so thumbs up on this article.
My question is how would I escape single or double quotes with your first example? For example, given the text:
"Jane's Defense Weekly"
I ended up looping endlessly by trying to replace "'" with "\'"; or I clearly don't understand how to escape quotes. I suspect there's probably a more elegant way of doing with with RegExp but you know better than me :)
Posted by Becks on Aug 27, 2007 at 4:25 AM
@Becks,
I am not sure what you mean. You shouldn't have to escape a single or double quote unless they are breaking the way you write the text in the first place. Escaping a quote doesn't actually change the character, it just tells the Javascript parsing engine NOT to end the current string but rather to treat the escaped quote as a character literal within the string value.
What are you trying to do?
Posted by Ben Nadel on Aug 27, 2007 at 7:28 AM
Sorry if my question was vague, I'm using Ajax to send queries to an Oracle database.
The problem I was having was that for Oracle strings containing the single quote (') need to have it escaped. So I know typically you'd ensure that the value you send to the database is something like this:
"Jane\'s Defense Weekly"
This way you don't get an SQL error. With your first example I found that I was going into an endless look because I was using the wrong syntax. Using the RegExp example, I solved my problem.
I also found out for oracle single quotes are escape with another single quote and not the slash like in JavaScript or Java strings.
Posted by becks on Aug 28, 2007 at 11:55 AM
Ahh, ok cool. Glad you got it working.
Posted by Ben Nadel on Aug 28, 2007 at 12:11 PM
Great article, how can you replace two different characters in the one expression for example if it finds < replace with < if it finds > replace with >?
Posted by Ryan on Oct 13, 2007 at 9:11 PM
Sorry in my last post it was supposed to show the html character set for less than and greater than (& lt; & & gt;)
Posted by Ryan on Oct 13, 2007 at 9:13 PM
@Ryan,
All you would need to do is match on both those characters and then replace them in the given function. Something like this:
your_text.replace(
... new RegExp( "(<|>)", "gi" ),
... function( $0, $1 ){
...... if ( $1 == ">" ){
......... return( "& gt;" );
...... } else {
......... return( "& lt;" );
...... }
... }
);
Clearly, you wouldn't use periods, but you get the point I hope.
Posted by Ben Nadel on Oct 15, 2007 at 8:01 AM
Hi Ben,
the String.prototype.replaceAll variant is definitely the most elegant. I have just one litte improvement in mind:
it runs into an endless look when given identical parameters (can occur when used dynamically on data). i.e. a little
<code>if(strTarget == strSubString) return;</code>
would be helpful
Posted by Nikolaus on Nov 25, 2007 at 9:57 AM
@Nikolaus,
It shouldn't be endless because, in theory, the next match should be searched for after the point of the last match. So, even if you were to replace the existing match with itself, the matching engine should continue on with the rest of the string.
However, that is just my theory. I will check to see if that is a reality.
Posted by Ben Nadel on Nov 25, 2007 at 4:17 PM
Very helpful. Thanks for the post.
Here is the code which will replaces all double quote into escape sequence.
sStrValue = sStrValue.replace( new RegExp('(")', "gi" ),
function( $0, $1 )
{
if ( $1 == '"' )
{
return( '"' );
}
});
Posted by Kamal on Jan 18, 2008 at 9:32 AM
@Kamal,
I am not sure I am following what your code will do. I don't think you need the anonymous function; your regular expression does not have any optional patterns and there is not special logic in the sub function. Meaning, if the pattern is matched, your conditional if() statement will *not* be true.
Posted by Ben Nadel on Jan 20, 2008 at 10:22 AM
Your replaceAll code is *** NOT SAFE ***
You should be using javascript's regular expression support for this instead of a loop:
stringValue.replace(/something/g, "something else");
Your solution causes infinite loop. Example:
stringValue.replaceAll("&", "&");
In this scenario you'd like to replace all special characters of an XML element body.
Posted by calicoder on Jul 25, 2008 at 8:29 PM
previous post should be
stringValue.replaceAll("&", "& amp;");
** no space **
Posted by calicoder on Jul 25, 2008 at 8:32 PM
@Calicoder,
There can definitely be some complications. I know that with the Javascript "Exec" command( String.exec() ), I have run into some endless processing loops. You just have to be carefule about how you replace and how you define the flags (if I remember correctly, the lack of the global flag, "g", messed me up in the exec() experiment). Of course, all of these things should be ironed out in development, pre-production.
Posted by Ben Nadel on Jul 28, 2008 at 9:56 AM