Trim specific character from a string
One line is enough:
var x = '|f|oo||';var y = x.replace(/^\|+|\|+$/g, '');document.write(x + '<br />' + y);
^ beginning of the string\|+ pipe, one or more times| or\|+ pipe, one or more times$ end of the string
A general solution:
function trim (s, c) { if (c === "]") c = "\\]"; if (c === "^") c = "\\^"; if (c === "\\") c = "\\\\"; return s.replace(new RegExp( "^[" + c + "]+|[" + c + "]+$", "g" ), "");}chars = ".|]\\^";for (c of chars) { s = c + "foo" + c + c + "oo" + c + c + c; console.log(s, "->", trim(s, c));}
Parameter c
is expected to be a character (a string of length 1).
As mentionned in the comments, it might be useful to support multiple characters, as it's quite common to trim multiple whitespace-like characters for example. To do this, MightyPork suggests to replace the if
s with the following line of code:
c = c.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
This part [-/\\^$*+?.()|[\]{}]
is a set of special characters in regular expression syntax, and $&
is a placeholder which stands for the matching character, meaning that the replace
function escapes special characters. Try in your browser console:
> "{[hello]}".replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')"\{\[hello\]\}"
If I understood well, you want to remove a specific character only if it is at the beginning or at the end of the string (ex: ||fo||oo||||
should become foo||oo
). You can create an ad hoc function as follows:
function trimChar(string, charToRemove) { while(string.charAt(0)==charToRemove) { string = string.substring(1); } while(string.charAt(string.length-1)==charToRemove) { string = string.substring(0,string.length-1); } return string;}
I tested this function with the code below:
var str = "|f|oo||";$( "#original" ).html( "Original String: '" + str + "'" );$( "#trimmed" ).html( "Trimmed: '" + trimChar(str, "|") + "'" );
Update: Was curious around the performance of different solutions and so I've updated a basic benchmark here:https://www.measurethat.net/Benchmarks/Show/12738/0/trimming-leadingtrailing-characters
Some interesting and unexpected results running under Chrome.https://www.measurethat.net/Benchmarks/ShowResult/182877
+-----------------------------------+-----------------------+| Test name | Executions per second |+-----------------------------------+-----------------------+| Index Version (Jason Larke) | 949979.7 Ops/sec || Substring Version (Pho3niX83) | 197548.9 Ops/sec || Regex Version (leaf) | 107357.2 Ops/sec || Boolean Filter Version (mbaer3000)| 94162.3 Ops/sec || Spread Version (Robin F.) | 4242.8 Ops/sec |+-----------------------------------+-----------------------+
Please note; tests were carried out on only a single test string (with both leading and trailing characters that needed trimming). In addition, this benchmark only gives an indication of raw speed; other factors like memory usage are also important to consider.
If you're dealing with longer strings I believe this should outperform most of the other options by reducing the number of allocated strings to either zero or one:
function trim(str, ch) { var start = 0, end = str.length; while(start < end && str[start] === ch) ++start; while(end > start && str[end - 1] === ch) --end; return (start > 0 || end < str.length) ? str.substring(start, end) : str;}// Usage:trim('|hello|world|', '|'); // => 'hello|world'
Or if you want to trim from a set of multiple characters:
function trimAny(str, chars) { var start = 0, end = str.length; while(start < end && chars.indexOf(str[start]) >= 0) ++start; while(end > start && chars.indexOf(str[end - 1]) >= 0) --end; return (start > 0 || end < str.length) ? str.substring(start, end) : str;}// Usage:trimAny('|hello|world ', [ '|', ' ' ]); // => 'hello|world'// because '.indexOf' is used, you could also pass a string for the 2nd parameter:trimAny('|hello| world ', '| '); // => 'hello|world'
EDIT: For fun, trim words (rather than individual characters)
// Helper function to detect if a string contains another string// at a specific position. // Equivalent to using `str.indexOf(substr, pos) === pos` but *should* be more efficient on longer strings as it can exit early (needs benchmarks to back this up).function hasSubstringAt(str, substr, pos) { var idx = 0, len = substr.length; for (var max = str.length; idx < len; ++idx) { if ((pos + idx) >= max || str[pos + idx] != substr[idx]) break; } return idx === len;}function trimWord(str, word) { var start = 0, end = str.length, len = word.length; while (start < end && hasSubstringAt(str, word, start)) start += word.length; while (end > start && hasSubstringAt(str, word, end - len)) end -= word.length return (start > 0 || end < str.length) ? str.substring(start, end) : str;}// Usage:trimWord('blahrealmessageblah', 'blah');