» Javascript equivalent for PHP's str_replace

PHP to Javascript Project: php.js

php.jsThis article is part of the 'Porting PHP to Javascript' Project, which aims to decrease the gap between developing for PHP & Javascript.

A lot of people are familiar with PHP's functions, and though Javascript functions are often quite similar, some functions may be missing or addressed differently. The Javascript implementations should be as compliant with the PHP versions as possible, a good indication is that the PHP function manual could also apply to the Javascript version.

Porting crucial PHP functions to Javascript can be fun & useful. Currently some PHP functions have been added, but readers are encouraged to contribute and improve functions by adding comments. Eventually the goal is to save all the functions in one php.js file and make it publicly available for your coding pleasure.

If you choose to contribute, let me know how you want to be credited in the function's comments. You may also want to subscribe to RSS so you receive updates whenever new functions are posted.

This is a Javascript version of the PHP function: str_replace.

PHP str_replace

Description

str_replace - Replace all occurrences of the search string with the replacement string

mixed str_replace( mixed search , mixed replace , mixed subject [, int &count] )

This function returns a string or an array with all occurrences of search in subject replaced with the given replace value.

Parameters

If search and replace are arrays, then str_replace() takes a value from each array and uses them to do search and replace on subject . If replace has fewer values than search , then an empty string is used for the rest of replacement values. If search is an array and replace is a string, then this replacement string is used for every value of search . The converse would not make sense, though.

If search or replace are arrays, their elements are processed first to last.

  • search
  • replace
  • subject

    If subject is an array, then the search and replace is performed with every entry of subject , and the return value is an array as well.

  • count

    Note: If passed, this will hold the number of matched and replaced needles.

Return Values

This function returns a string or an array with the replaced values.

See Also

Javascript str_replace

Source

This is the main source of the Javascript version of PHP's str_replace

function str_replace(search, replace, subject) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // +   improved by: Simon Willison (http://simonwillison.net)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // -    depends on: is_array
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
    // *     returns 2: 'hemmo, mars'    
    
    var f = search, r = replace, s = subject;
    var ra = is_array(r), sa = is_array(s), f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;
 
    while(j = 0, i--){
        while(s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f);
    }
     
    return sa ? s : s[0];
}

To run the Javascript str_replace, you will also need the following dependencies:

Examples

Currently there are 2 examples

Example 1

This is how you could call str_replace()
str_replace(' ', '.', 'Kevin van Zonneveld');
And that would return
'Kevin.van.Zonneveld'

Example 2

This is how you could call str_replace()
str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
And that would return
'hemmo, mars'

More about this Project

Download php.js

To easily include it in your code, every function currently available is stored in

Normal

Namespaced What is 'namespaced?'

To download use Right click, Save Link As
Generally the best way is to use a minified version and gzip it



Testing the functions

The number of functions is growing fast and so it becomes hard to maintain quality.

To defeat that danger of bad code, syntax errors, etc, I've added a new feature: php.js tester.

It is an automatically generated page that includes ALL functions in your browser, and then extracts specific testing information from each function's comments. This info is then used to run the function, and the return value is compared to a predefined one.

This way code is always checked on syntax errors, and if it doesn't function correctly anymore after an update, we should also be able to detect it more easily.

If you want, go check it out.


Credits

Respect & awards go to everybody who has contributed in some way so far:

medalmedalMichael White (link) for contributing to:
 array_count_values, get_included_files, include, include_once, require, require_once, md5, number_format, parse_str, printf, sha1, sprintf, str_pad, strnatcmp, http_build_query, floatval, is_object, print_r
spacemedal_argos for contributing to:
 array_fill, array_pad, array_product, array_rand, compact, count, range, abs, defined, ip2long, long2ip, implode, strcmp, ucwords
spacemedalJonas Raoni Soares Silva (link) for contributing to:
 shuffle, abs, setcookie, number_format, number_format, soundex, str_repeat, str_replace, str_rot13, ucwords, wordwrap, wordwrap
spacemedalLegaev Andrey for contributing to:
 end, reset, file, file_get_contents, function_exists, include, include_once, http_build_query, is_array, is_object
spacemedalAtes Goral (link) for contributing to:
 array_change_key_case, array_count_values, array_diff_key, get_class, preg_quote, addslashes, count_chars, str_rot13, stripslashes
spacemedalPhilip Peterson for contributing to:
 sizeof, round, echo, nl2br, str_replace, strchr, urldecode, urlencode, var_export
spacemedalMartijn Wieringa for contributing to:
 str_ireplace, str_split, strcasecmp, stripos, strnatcmp, substr
spacemedalWebtoolkit.info (link) for contributing to:
 crc32, md5, sha1, utf8_decode, utf8_encode
 
spacemedalCarlos R. L. Rodrigues (link) for contributing to:
 array_chunk, array_unique, date, levenshtein
spacemedalAsh Searle (link) for contributing to:
 basename, printf, sprintf
spacemedalErkekjetter for contributing to:
 ltrim, rtrim, trim
spacemedalmarrtins for contributing to:
 array_change_key_case, addslashes, stripslashes
spacemedalAlfonso Jimenez (link) for contributing to:
 array_reduce, strpbrk
spacemedalAman Gupta for contributing to:
 base64_decode, utf8_decode
spacemedalArpad Ray (mailto:arpad@php.net) for contributing to:
 serialize, unserialize
spacemedalKarol Kowalski for contributing to:
 array_reverse, abs
spacemedalThunder.m for contributing to:
 base64_decode, base64_encode
spacemedalTyler Akins (link) for contributing to:
 base64_decode, base64_encode
spacemedalmdsjack (link) for contributing to:
 include, trim
spacemedalAlexander Ermolaev (link) for contributing to:
 trim
spacemedalAllan Jensen (link) for contributing to:
 number_format
spacemedalAndrea Giammarchi (link) for contributing to:
 array_map
spacemedalBayron Guevara for contributing to:
 base64_encode
spacemedalBenjamin Lupton for contributing to:
 number_format
spacemedalBrad Touesnard for contributing to:
 date
spacemedalBrett Zamir for contributing to:
 str_split
spacemedalCagri Ekin for contributing to:
 parse_str
spacemedalCord for contributing to:
 is_array
spacemedalDavid for contributing to:
 is_numeric
spacemedalDavid James for contributing to:
 get_class
spacemedalDxGx for contributing to:
 trim
spacemedalFGFEmperor for contributing to:
 mktime
spacemedalFelix Geisendoerfer (link) for contributing to:
 array_key_exists
spacemedalFremyCompany for contributing to:
 isset
spacemedalGabriel Paderni for contributing to:
 str_replace
spacemedalLeslie Hoare for contributing to:
 rand
spacemedalLincoln Ramsay for contributing to:
 basename
spacemedalMeEtc (link) for contributing to:
 date
spacemedalMick@el for contributing to:
 stripslashes
spacemedalNick Callen for contributing to:
 wordwrap
spacemedalOzh for contributing to:
 dirname
spacemedalPedro Tainha (link) for contributing to:
 unserialize
spacemedalPeter-Paul Koch (link) for contributing to:
 date
spacemedalPhilippe Baumann for contributing to:
 empty
spacemedalSakimori for contributing to:
 strlen
spacemedalSanjoy Roy for contributing to:
 array_diff
spacemedalSimon Willison (link) for contributing to:
 str_replace
spacemedalSteve Clay for contributing to:
 function_exists
spacemedalSteve Hilder for contributing to:
 strcmp
spacemedalSteven Levithan (link) for contributing to:
 trim
spacemedalT0bsn for contributing to:
 crc32
spacemedalThiago Mata (link) for contributing to:
 call_user_func_array
spacemedalTim Wiel for contributing to:
 date
spacemedalXoraX (link) for contributing to:
 dirname
spacemedalbaris ozdil for contributing to:
 mktime
spacemedalbooeyOH for contributing to:
 preg_quote
spacemedaldjmix for contributing to:
 basename
spacemedalduncan for contributing to:
 array_unique
spacemedalecho is bad for contributing to:
 echo
spacemedalgabriel paderni for contributing to:
 mktime
spacemedalger for contributing to:
 html_entity_decode
spacemedaljohn (link) for contributing to:
 html_entity_decode
spacemedalkenneth for contributing to:
 explode
spacemedalpenutbutterjelly for contributing to:
 str_ireplace
spacemedalstensi for contributing to:
 intval

Your name here?

Contributing is as easy as adding a comment with better code, or code for a new function.
Any contribution leading to improvement will directly get your name & link here.


Coming Project features

Project features that we are currently working on:

  • Versioning. Individual functions are versioned, but the entire library should be versioned as well.
  • Light. A lightweight version of php.js should be made available with only common functions in it.

Like this article?

   Then Dzone it!
Or use another bookmark button below to show your support &
help me spread the word.


tags: programming, php, javascript
category: Programming - Javascript - PHP equivalents
read: 2,612 times

Add comment

for syntax highlighting

[CODE="Javascript"]
your_code_here();
[/CODE]

Replace "Javascript"
with "php", "text", etc.
code (to make sure you are not a spammer)

Comments

#21. Kevin on 18 April 2008

Kevin@ Jonas Raoni: That's astonishing :D The non-overlapping approach was convincing enough for me not to take the effort to test if this was the actual mechanism of PHP. It would make sense though right? Anyway, I will reinstate your version Jonas Raoni, and adjust the test case. Thanks for all of your work! You too Peter, some functions come easy, some tend to be a little of a pain. But that's the challenge & learning experience, right.

#20. Philip on 18 April 2008

PhilipThat is incredibly weird... I was certain that PHP replaced all the stuff at once so as not to create overlap... ah well, I guess it's not like that after all. It was a cool function though :P

#19. Jonas Raoni on 18 April 2008

Jonas RaoniI didn't looked the comments before, I just saw the code was long and made a version :)~

But it's strange... What php version are you using? The following code, on php 5, gave me as output "hemmo, mars":

echo str_replace(array('{name}', 'l'), array('hello', 'm'), '{name}, lars');

#18. Philip Peterson on 18 April 2008

Philip PetersonWoah, I didn't see comments #16 or #15... hmm, I'm surprised, it definitely has merit, though...

#17. Philip Peterson on 18 April 2008

Philip PetersonWow... bravo is all I can say... that's more than 20x faster than my code, too, lol...

#16. Kevin on 17 April 2008

Kevin@ Jonas Raoni: I've updated, committed, generated, deployed, tested, reverted, commited, generated & deployed ;) And srry dude but your str_replace did not survive Peter's testcase:

// should return: hello, mars
str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
More info in the comments here. Guess I'll be needing those medals back ;) nah just kidding :)

#15. Kevin on 17 April 2008

Kevin@ Jonas Raoni: That looks very promising :) I still have to test it but if you have reduced our function to this, preserving all of it's functionality, then you deserve 3 medals ;)

#14. Jonas Raoni on 17 April 2008

Jonas RaoniI just made this code, it's using the already present is_array function.

function str_replace(f, r, s){
var ra = is_array(r), sa = is_array(s), f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;
while(j = 0, i--)
... [more] while(s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f);
return sa ? s : s[0];
}

Example:

alert(str_replace(["a", "fb", "c"], ["f", "g"], ["abcd"]));

#13. Kevin on 15 April 2008

Kevin@ Philip Peterson: If you like you can now do this in SVN ;)

#12. Philip Peterson on 15 April 2008

Philip PetersonHmm, I actually can see where that could come in useful though...

nsub = nsub.replace(new RegExp(__regexp_escape(search[x]), "g"), "[cod"+fincods[x]+"]");
 
could work with
 
nsub = nsub.split(search[x]).join("[cod"+fincods[x]+"]");
and that sort of thing occurs in four places, so there's a significant drop in size, and you probably can even drop that __regexp_escape function [sorry Simon :(]. You probably should keep him in the credits though, even if you take the function out.

#11. Kevin on 13 April 2008

Kevin@ Jonas Raoni: Hi there, how have you been? Thats a brutal approach :) However the long code we have now supports some features that your approach does not. For more information see the comments here. Thanks for this insightful way though!

#10. Jonas Raoni on 12 April 2008

Jonas RaoniFor the str_replace the best and fastest method I know it's:

"Jonas Raoni".split("a").join("X");

#9. Kevin on 31 March 2008

Kevin@ Philip: Cool, I've included Simon as well. Thanks again.

#8. Philip on 31 March 2008

PhilipNo problem!

Also: Credits to Simon Willison (http://simonwillison.net/2006/Jan/20/escape/) for the regexp_escape function.

#7. Kevin on 31 March 2008

Kevin@ Philip: A seemingly straightforward function like str_replace turns out to be more complex than e.g. mktime :) I've indented your code and included the extra function (had to 'var' it for namespacing compatibility) in str_replace.

Thanks A LOT for seriously improving this function!

#6. Philip on 31 March 2008

PhilipNot necessarily; what if a result produced by the replacement of one of the shorter strings produced the values of one of the longer searches? Here's a code that works, but I haven't indented the part that I made yet, or commented it, and it requires a second external function... I dunno if you can fix that or not.

// http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
 
function regexp_escape(text) {
  if (!arguments.callee.sRE) {
    var specials = [
      '/', '.', '*', '+', '?', '|',
      '(', ')', '[', ']', '{', '}', '\\'
    ];
    arguments.callee.sRE = new RegExp(
      '(\\' + specials.join('|\\') + ')', 'g'
    );
  }
  return text.replace(arguments.callee.sRE, '\\$1');
}
 
function str_replace(search, replace, subject)
{
 
    if(!(replace instanceof Array)){
        replace=new Array(replace);
        if(search instanceof Array){//If search    is an array and replace    is a string, then 
 
this replacement string is used for every value of search
            while(search.length>replace.length){
                replace[replace.length]=replace[0];
            }
        }
    }
 
    if(!(search instanceof Array))search=new Array(search);
    while(search.length>replace.length){//If replace    has fewer values than search , then an 
 
empty string is used for the rest of replacement values
        replace[replace.length]='';
    }
 
    if(subject instanceof Array){//If subject is an array, then the search and replace is 
 
performed with every entry of subject , and the return value is an array as well.
        for(k in subject){
            subject[k]=str_replace(search,replace,subject[k]);
        }
        return subject;
    }
 
 
 
 
numreplx=search.length;
numon=0;
fincods=new Array();
while(fincods.length<numreplx)
{
nsub=subject;
for(x=0;x<fincods.length;x++)
{
nsub=nsub.replace(new RegExp(regexp_escape(search[x]), "g"), "[cod"+fincods[x]+"]");
}
for(x=0;x<fincods.length;x++)
{
nsub=nsub.replace(new RegExp(regexp_escape("[cod"+fincods[x]+"]"), "g"), replace[x]);
}
if(nsub.indexOf("[cod"+numon+"]") == -1)
{
fincods[fincods.length]=numon;
}
numon++;
}
for(x=0;x<fincods.length;x++)
{
subject=subject.replace(new RegExp(regexp_escape(search[x]), "g"), "[cod"+fincods[x]+"]");
}
for(x=0;x<fincods.length;x++)
{
subject=subject.replace(new RegExp(regexp_escape("[cod"+fincods[x]+"]"), "g"), replace[x]);
}
return subject;
}

#5. Kevin on 31 March 2008

Kevin@ Philip: Thanks for noticing. My first thought is to order the search array by length, ascending. This way 'l' will be searched & replaced before hello will be.
Do you agree that that would solve the issue?

#4. Philip on 30 March 2008

PhilipThere's only a slight problem with this code... in PHP, each entry is replaced all at once, rather than one after another. This creates a problem in the following example:

function parseInf(kyl){
 
kyl=str_replace([
"{name}",
"l"
],
[
"hello",
"m"
],
kyl);
 
 
nev=kyl.split(/\r{0,1}\n-\r{0,1}\n/);
 
 
return nev;
 
 
}
 
alert(parseInf("{name}, lars"));
Theoretically, the code should return "hello, mars", but instead it returns "hemmo, mars". It completes the first iteration before the second, rather than all at once.

#3. Kevin on 02 March 2008

Kevin@ G.Paderni: Good point! Thank you for contributing!

#2. G.Paderni on 02 March 2008

G.Padernioh, sorry there's an error please remove my last comment this one is ok:

function str_replace(search,replace,subject) {
  // by: Gabriel Paderni
 
  if(!(replace instanceof Array)){
    replace=new Array(replace);
    if(search instanceof Array){//If search  is an array and replace  is a string, then this replacement string is used for every value of search
      while(search.length>replace.length){
        replace[replace.length]=replace[0];
      }
    }
  }
 
  if(!(search instanceof Array))search=new Array(search);
  while(search.length>replace.length){//If replace  has fewer values than search , then an empty string is used for the rest of replacement values
    replace[replace.length]='';
  }
 
  if(subject instanceof Array){//If subject is an array, then the search and replace is performed with every entry of subject , and the return value is an array as well.
    for(k in subject){
      subject[k]=str_replace(search,replace,subject[k]);
    }
    return subject;
  }
  
  for(var k=0; k<search.length; k++){
    var i = subject.indexOf(search[k]);
    while(i>-1){
      subject = subject.replace(search[k], replace[k]);
      i = subject.indexOf(search[k],i);
    }
  }
 
  return subject;
}

#1. sbsweb on 19 February 2008

sbswebIncreible, ese .js es de lo más útil que he visto.