Trim specific character from a string

混江龙づ霸主 提交于 2019-11-27 07:55:40

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

In a function :

function trim (s, c) {
  if (c === "]") c = "\\]";
  if (c === "\\") c = "\\\\";
  return s.replace(new RegExp(
    "^[" + c + "]+|[" + c + "]+$", "g"
  ), "");
}

s = ".foo..oo...";
console.log(s, "->", trim(s, "."));
s = "|foo||oo|||";
console.log(s, "->", trim(s, "|"));
s = "]foo]]oo]]]";
console.log(s, "->", trim(s, "]"));
s = "\\foo\\\\oo\\\\\\";
console.log(s, "->", trim(s, "\\"));
Pho3niX83

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, "|") + "'" );

You can use a regular expression such as:

var x = "|f|oo||";
var y = x.replace(/^[\|]+|[\|]+$/g, "");
alert(y); // f|oo

UPDATE:

Should you wish to generalize this into a function, you can do the following:

var escapeRegExp = function(strToEscape) {
    // Escape special characters for use in a regular expression
    return strToEscape.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};

var trimChar = function(origString, charToTrim) {
    charToTrim = escapeRegExp(charToTrim);
    var regEx = new RegExp("^[" + charToTrim + "]+|[" + charToTrim + "]+$", "g");
    return origString.replace(regEx, "");
};

var x = "|f|oo||";
var y = trimChar(x, "|");
alert(y); // f|oo

to keep this question up to date:

here is an approach i'd choose over the regex function using the ES6 spread operator.

function trimByChar(string, character) {
  const first = [...string].findIndex(char => char !== character);
  const last = [...string].reverse().findIndex(char => char !== character);
  return string.substring(first, string.length - last);
}

This can trim several characters at a time:

String.prototype.trimChars = function (c) {
  var re = new RegExp("^[" + c + "]+|[" + c + "]+$", "g");
  return this.replace(re,"");
}

var x = "|f|oo||"; 
x =  x.trimChars('|'); // f|oo

var y = "..++|f|oo||++..";
y = y.trimChars('|.+'); // f|oo

var z = "\\f|oo\\"; // \f|oo\

// For backslash, remember to double-escape:
z = z.trimChars("\\\\"); // f|oo

Regex seems a bit too complex for a simple problem like Trim?

C#

var x = "|f|oo||"; 
var y = x.Trim('|'); //  "f|oo"

Javascript, x.TrimLeft('|') example - simple (but trims only single character)

var ltrim = "|";
var x = "|f|oo||";
var y = (x.startsWith(ltrim) ? x.substring(ltrim.length) : x); // "f|oo||"

var result = y;
console.log(y);

Javascript full example (thanks to @Tobo answer and @rooby suggestion)

class SutString extends String { // [S]tring[Ut]ility
  replaceFirstOnly(src, dest) {
    return new SutString(this.replace(src, dest)); // String.replace is misleading
  }
  replaceAll(src, dest) {
    return new SutString(this.split(src).join(dest));
  }

  reverse() {
    return new SutString(this.split("").reverse().join(""));
  }

  trimStart(delimiter = " ") {
    if (!delimiter) {
      return this.replace(/^\s+/gm, '');
    }

    var current = this; var index = this.length;
    while(current.startsWith(delimiter) && index >= 0) {
      current = current.substring(delimiter.length);
      --index;
    }
    if (typeof(current) === 'string') {
      return new SutString(current);
    }
    return current;
  };

  trimEnd(delimiter = " ") {
    if (!delimiter) {
      return new SutString(this.reverse().replace(/^\s+/gm, '')).reverse();
    }

    var current = this; var index = this.length;
    while(current.endsWith(delimiter) && index >= 0) {
      current = current.substring(0, this.length - delimiter.length - 1);
      --index;
    }
    if (typeof(current) === 'string') {
      return new SutString(current);
    }
    return current;
  };

  trimString(delimiter = " ") {
    if (!delimiter) {
      return this.trim();
    }

    return this.trimStart(delimiter).trimEnd(delimiter);
  };
}
// Pushes all functions and properties from String to SutString,
//   returning SutString if the result is a string
for(let prop of Object.getOwnPropertyNames(String.prototype)) {
  if (prop === "constructor" || prop === "toString" || (""[prop]) instanceof Function) {
    continue;
  }
  let newprop = prop;
  if (typeof(SutString.prototype[prop]) !== 'undefined') {
    newprop = "base_" + prop;
  }
  SutString.prototype[newprop] = function() {
    const result = this.toString()[prop].apply(this, arguments);
    if (typeof(result) !== 'string') {
      return result;
    }
    return new SutString(result);
  }
}
var str = new SutString("|f|oo||");
var strWhitespace = new SutString(" |f|oo||  ");

console.log("\"" + str.trimStart("|") + "\" ===", "\"" + str + "\".trimStart(\"|\");");
console.log("\"" + str.trimEnd("|") + "\" ===", "\"" + str + "\".trimEnd(\"|\");");
console.log("\"" + str.trimString("|") + "\" ===", "\"" + str + "\".trimString(\"|\");");

console.log("\"" + strWhitespace.trimStart() + "\" ===", "\"" + strWhitespace + "\".trimStart();");
console.log("\"" + strWhitespace.trimEnd() + "\" ===", "\"" + strWhitespace + "\".trimEnd();");
console.log("\"" + strWhitespace.trimString() + "\" ===", "\"" + strWhitespace + "\".trimString();");

I was a little lazy with trimStart and trimEnd. It would be more efficient to find how much of each side needs trimmed. Then call substring only once. But hopefully you get the idea and this is helpful!

Note: This is es6 specific. Some of this may be implemented for you in es2019.

A regex-less version which is easy on the eye:

const trim = (str, chars) => str.split(chars).filter(Boolean).join(chars);

For use cases where we're certain that there's no repetition of the chars off the edges.

This one trims all leading and trailing delimeters

const trim = (str, delimiter) => {
  const pattern = `[^\\${delimiter}]`;
  const start = str.search(pattern);
  const stop = str.length - str.split('').reverse().join('').search(pattern);
  return str.substring(start, stop);
}

const test = '||2|aaaa12bb3ccc|||||';
console.log(trim(test, '|')); // 2|aaaa12bb3ccc

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'

To my knowledge, jQuery doesnt have a built in function the method your are asking about. With javascript however, you can just use replace to change the content of your string:

x.replace(/|/i, ""));

This will replace all occurences of | with nothing.

expanding on @leaf 's answer, here's one that can take multiple characters:

var trim = function (s, t) {
  var tr, sr
  tr = t.split('').map(e => `\\\\${e}`).join('')
  sr = s.replace(new RegExp(`^[${tr}]+|[${tr}]+$`, 'g'), '')
  return sr
}

I like the solution from @Pho3niX83...

Let's extend it with "word" instead of "char"...

function trimWord(_string, _word) {

    var splitted = _string.split(_word);

    while (splitted.length && splitted[0] === "") {
        splitted.shift();
    }
    while (splitted.length && splitted[splitted.length - 1] === "") {
        splitted.pop();
    }
    return splitted.join(_word);
};

I would suggest looking at lodash and how they implemented the trim function.

See Lodash Trim for the documentation and the source to see the exact code that does the trimming.

I know this does not provide an exact answer your question, but I think it's good to set a reference to a library on such a question since others might find it useful.

function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}

try:

console.log(x.replace(/\|/g,''));
Tobo
String.prototype.TrimStart = function (n) {
    if (this.charAt(0) == n)
        return this.substr(1);
};

String.prototype.TrimEnd = function (n) {
    if (this.slice(-1) == n)
        return this.slice(0, -1);
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!