2

I've a string say for example

var str = "this is 'a simple' a simple 'string' string"

I want to replace all 's' characters as, say for example 'p' characters.

str =  "thip ip 'a simple' a pimple 'string' ptring"

What would be the correct way to approach this?

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
neeru
  • 259
  • 1
  • 3
  • 11

5 Answers5

5

We break it to tokens and parse it in good ol' way:

  • Go through the string one char at a time
  • If you encounter a ' set your state to 'not replacing' if it was replacing, otherwise set it to replacing.
  • When you encounter an s and your state is replacing, replace it with a p

This solution does not support nesting of '.

var tokens = yourString.split("");
var inQuotes = false;
for(var i=0;i<tokens.length;i++){
    if(tokens[i] == "'"){
        inQuotes = !inQuotes;
    }else 
    if(!inQuotes && tokens[i] == 's'){
        tokens[i] = 'p'
    }
}

var result = tokens.join("");

Here is a fiddle

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • +1, but I think this gets very complicated if he ever wants to search for a string that is more than 1 char. Also, why split into tokens instead of using `yourString.charAt(i)`? – Wutz Aug 02 '13 at 10:28
  • @Wutz Strings are immutable, note I'm also _setting_ to it and not just reading from it. If we want to search for a string that is more than one character there is no way around actual tokens for that scenario :) – Benjamin Gruenbaum Aug 02 '13 at 10:29
  • It couldn't be done more complicated... a regexp, like @Vanga Sasidhar's takes care of all this house keeping. You should not reinvent the basic functions. – allprog Aug 02 '13 at 10:31
  • 1
    @allprog Sure it could be 'done more complicated'. A regexp is a very limited tool - it should be used only when helpful and clear. Sure - you can come up with a deterministic finite automaton for this fairly easily with such states - but creating the actual correct regular expression for it can be a real hassle and is not a very clear one (note what OP is _really_ trying to accomplish for stuff inside and outside of quotes). A solution that does tokenization is perfectly fine - regex should only be used when helpful. – Benjamin Gruenbaum Aug 02 '13 at 10:35
  • @BenjaminGruenbaum Ok, it's impossible to do with a single regexp. I didn't take care of the circumstance that the outside/inside is different. Kudos to you! In retrospect, I could hardly come up with shorter code. – allprog Aug 02 '13 at 11:08
2

I would go for a function like

splitStr = str.split("'");
for(var i = 0; i < splitStr.length; i=i+2){
    splitStr[i].replace(/s/g, "p");
}
str = splitStr.join("'");
Nicola Miotto
  • 3,647
  • 2
  • 29
  • 43
  • 1
    Note that `.replace` with a string only replaces the _first_ instance. You might want to use replace with a regex and the `g` flag if you want it to work – Benjamin Gruenbaum Aug 02 '13 at 10:28
2

Here's what I'd do:

var str = "this is 'a simple' a simple 'string' string",
quoted = str.match(/'[^']+'/g);//get all quoted substrings
str =str.replace(/s/g,'p');
var restore = str.match(/'[^']+'/g);
for(var i = 0;i<restore.length;i++)
{
    str = str.replace(restore[i], quoted[i]);
}
console.log(str);//logs "thip ip 'a simple' a pimple 'string' ptring"

Of course, to be clean, the code I'd actually use would be:

var str = (function(str)
{
    var i,quoteExp = /'[^']+'/g,
    quoted = str.match(quoteExp),
    str = str.replace(/s/g, 'p'),
    restore = str.match(quoteExp);
    for(i=0;i<restore.length;i++)
    {
        str.replace(restore[i], quoted[i]);
    }
    return str;
}("this is 'a simple' a simple 'string' string"));
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
0
function myReplace(string) {
  tabString = string.split("'");
  var formattedString = '';
  for(i = 0; typeof tabString[i] != "undefined"; i++){
    if(i%2 == 1) {
      formattedString = formattedString + "'" + tabString[i] + "'";
    } else {
      formattedString = formattedString + tabString[i].replace(/s/g, 'p');
    }
  }
  return formattedString;
}
Guillaume Lhz
  • 904
  • 5
  • 16
0

JavaScript does not support lookahead and lookbehind matching, so a bit of manual labor is required:

// Source string
var str = "this is 'a simple' a simple 'string' string";

// RegEx to match all quoted strings.
var QUOTED_EXP = /\'[\w\s\d]+\'/g; 

// Store an array of the unmodified quoted strings in source
var quoted = str.match(QUOTED_EXP); 

// Do any desired replacement
str = str.replace('s', 'p'); // Do the replacement

// Put the original quoted strings back
str = str.replace(QUOTED_EXP, function(match, offset){
    return quoted.shift();
});

Fiddle: http://jsfiddle.net/Zgbht/

nordhagen
  • 799
  • 5
  • 18