1

By using Javascript, I want to convert text

"  [a] b    [c]" 

to

"[a] b [c]"

My code as below:

var test = "  [a] b    [c]";
test.replace(/\s+\[/g, "[");
alert(test);

However, the result is

"[a] b    [c]"

I wonder why? Any idea?

Thanks!

adarshr
  • 61,315
  • 23
  • 138
  • 167
Santiago Munez
  • 1,965
  • 5
  • 18
  • 16

2 Answers2

3

Strings are immutable. So replace doesn't change test but returns a changed string. Hence, you need to assign the result:

test = test.replace(/\s+\[/g, "[");

Note that this will result in [a] b[c]. To get your actual result, you might want to use:

test = test.replace(/(^|\s)\s*\[/g, "$1[");

This makes sure to write back the first of the space characters if it was not at the beginning of the string.

Alternatively, use trim first and write back one space manually:

test = test.trim().replace(/\s+\[/g, " [");
Martin Ender
  • 43,427
  • 11
  • 90
  • 130
  • Yes, but now I wonder why did the string change in the OP example. ) – raina77ow Aug 18 '13 at 16:33
  • 2
    @raina77ow because he didn't see the leading spaces in the alert box (if they were rendered at all) – Martin Ender Aug 18 '13 at 16:34
  • Argh, but of course. @SantiagoMunez - make a habit using `console.log` instead of `alert` to debug things. ) – raina77ow Aug 18 '13 at 16:35
  • Thanks! It works. Btw, do you mind to also explain the expression? test = test.replace(/(^|\s)\s*\[/g, "$1["); why my expression \s+ is not enough to achieve the objective that I want? – Santiago Munez Aug 18 '13 at 16:39
  • Why are you bothering with matching the `[` at all? – Mulan Aug 18 '13 at 16:43
  • This also **fails** if there is more than one space after `]`; – Mulan Aug 18 '13 at 16:45
  • @naomik because the OP apparently only wants to normalise spaces in front of `[`. at least he never mentioned anything else. – Martin Ender Aug 18 '13 at 17:28
  • @SantiagoMunez your attempt matches all spaces in front of all `[` and doesn't write any back. hence, you are just removing all spaces (see my example output). if you just added a space into the replacement (as in my last example) that would leave a leading space at the beginning of the string. hence, my second pattern makes sure that you either match the start of the string and capture nothing - or a single space anywhere else in the string - and writes it back with `$1`, so that through that condition you always get the right behaviour. – Martin Ender Aug 18 '13 at 17:36
  • @m.buettner, well I guess we're both wrong. The OP never explicitly said that he wanted to "normalize spaces only in front of `[`". I would argue that your solution is more specific, more rigid, and therefore not as good. – Mulan Aug 19 '13 at 05:59
  • @naomik well, I inferred that from the OP's own attempt. also even the question's title mentions the "special character". his opinion would help here. – Martin Ender Aug 19 '13 at 09:57
1

Trim

test = test.replace(/(^\s+|\s+$)/g, test);

Or you can use str.trim() if your browser supports it

test = test.trim();

note: if your need to support a browser that doesn't offer str.trim, you can always use es5-shim


Compact spaces to one

test = test.replace(/\s+/g, " ");

A one-liner

test = test.trim().replace(/\s+/g, " ");

A couple tests

var cleanString = function(str) {
  console.log(str.trim().replace(/\s+/g, " "));
};

var examples = [
  "    [a]  b     [c]      ",
  " [a]    [b]    [c]   [d]",
  "[a]       b [c]         ",
  "              [a] b [c] "
];

examples.map(cleanString);

Output

[a] b [c]
[a] [b] [c] [d]
[a] b [c]
[a] b [c]
Mulan
  • 129,518
  • 31
  • 228
  • 259