修剪字符串中的特定字符


120

与该方法等效的JavaScript是什么C#

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

C#仅在字符串的开头结尾处修剪所选字符!

Answers:


155

一行就足够了:

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

通用解决方案:

function trim (s, 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));
}


35

如果我深知,要删除,只有当它是在开头或字符串末尾一个特定的字符(例如:||fo||oo||||应成为foo||oo)。您可以创建一个临时功能,如下所示:

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;
}

我使用以下代码测试了此功能:

var str = "|f|oo||";
$( "#original" ).html( "Original String: '" + str + "'" );
$( "#trimmed" ).html( "Trimmed: '" + trimChar(str, "|") + "'" );

3
对于垃圾收集器来说,这是一个有趣的测试,但是我不建议您让客户接受它。
Sorensen

18

您可以使用正则表达式,例如:

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

更新:

如果您希望将其概括为一个函数,可以执行以下操作:

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

17

使此问题保持最新:

这是我将使用ES6扩展运算符选择正则表达式功能的一种方法。

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);
}

@fabian注释后的改进版本(只能处理包含相同字符的字符串)

function trimByChar(string, character) {
  const arr = Array.from(string);
  const first = arr.indexOf(character);
  const last = arr.reverse().indexOf(character);
  return string.substring(first + 1, string.length - last - 1);
}

2
我知道正则表达式在这里过分杀人,但是为什么您会选择这种特定实现?
Nicholas Shanks

2
这种实现方式是因为我个人认为它可读性强。没有正则表达式只是因为正则表达式引擎中的决策“树”要大得多。尤其是因为用于修剪的正则表达式包含查询字符,这些查询字符会导致正则表达式引擎内的回溯。这样的引擎通常将模式编译成类似于机器指令的字节码。然后引擎执行代码,从一条指令跳到另一条指令。当指令失败时,它会回溯以找到另一种匹配输入的方法。ergo比nec进行的要多得多。
罗宾F.18年

感谢您的答复,尽管我想让您解释一下为什么您会选择这种方式而不是其他非正则表达式的方式-我想我希望更多的只是“我觉得它可读”。
Nicholas Shanks

1
@RobinF。您认为findIndex()和reverse()不包含循环?再想一想。
安德鲁

1
两个注释:仅包含要修剪的字符的字符串将完全不修剪。另一个要点是:使用传播运算符将字符串分解为数组将使babel混淆并将其转换[].concat(string)为不希望的结果。使用Array.from(string)将起作用。
Fabian

14

无需注册的无正则表达式版本:

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

对于可以肯定不会重复出现字符的用例。


很有意思...所以split返回等于每个分隔符的未定义元素const trim = (str, chars) => str.split(chars).filter(x => { Boolean(x); console.log(typeof(x), x, Boolean(x)); }).join(chars); const str = "#//#//abc#//test#//end#//"; console.log(trim(str, '#//'));
TamusJRoyce

10

如果您要处理更长的字符串,我认为这应该通过将分配的字符串数减少为零或一个来胜过大多数其他选择:

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'

或者,如果要从一组多个字符中修剪,请执行以下操作:

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'

编辑:为了好玩,修剪单词(而不是单个字符)

// 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');

1
我更喜欢这种解决方案,因为它实际上是有效的,而不是短暂的。
tekHedd

我同意应该首选。取代我给出的答案。
TamusJRoyce

9

一次可以修剪几个字符:

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

@fubo:不,不是真的。这是一个演示,如果将其粘贴到控制台中,它将仅打印出结果。但我知道它可能会造成混淆,因此我对其进行了编辑。
marlar

2

如果在程序中定义了这些功能,则字符串将具有trim可以修剪所有给定字符的升级版本:

String.prototype.trimLeft = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("^[" + charlist + "]+"), "");
};

String.prototype.trim = function(charlist) {
	return this.trimLeft(charlist).trimRight(charlist);
};

String.prototype.trimRight = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("[" + charlist + "]+$"), "");
};

var withChars = "/-center-/"
var withoutChars = withChars.trim("/-")
document.write(withoutChars)

资源

https://www.sitepoint.com/trimming-strings-in-javascript/


1

据我所知,jQuery没有您要询问的内置函数。但是,使用javascript,您可以仅使用replace来更改字符串的内容:

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

这将替换|的所有出现。一无所有。


有没有办法删除| 仅在开始/结束?
2014年

其实,我觉得这个职位将让你最快速了解你的问题:stackoverflow.com/questions/20196088/...
奥莱Haugset

@fubo当然... $只能在结束时扔这样的东西:"||spam|||".replace(/\|+$/g, "")^仅在开始时扔这样的东西:"||spam|||".replace(/^\|+/g, "")
ruffin

1

这个修剪所有前导和尾随的距离

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

1

我建议看看lodash以及它们如何实现该trim功能。

有关文档和源代码,请参见Lodash Trim代码,的确切代码。

我知道这不能为您的问题提供确切的答案,但是我认为最好在此类问题上建立对图书馆的引用,因为其他人可能会觉得有用。


1
@TamusJRoyce不一样
gdbdable

@devi我只能同意。谢谢你的意见。调查社区支持的工具的好答案。
TamusJRoyce

1

解决此任务的最佳方法是(类似于PHP trim函数):

function trim( str, charlist ) {
  if ( typeof charlist == 'undefined' ) {
    charlist = '\\s';
  }
  
  var pattern = '^[' + charlist + ']*(.*?)[' + charlist + ']*$';
  
  return str.replace( new RegExp( pattern ) , '$1' )
}

document.getElementById( 'run' ).onclick = function() {
  document.getElementById( 'result' ).value = 
  trim( document.getElementById( 'input' ).value,
  document.getElementById( 'charlist' ).value);
}
<div>
  <label for="input">Text to trim:</label><br>
  <input id="input" type="text" placeholder="Text to trim" value="dfstextfsd"><br>
  <label for="charlist">Charlist:</label><br>
  <input id="charlist" type="text" placeholder="Charlist" value="dfs"><br>
  <label for="result">Result:</label><br>
  <input id="result" type="text" placeholder="Result" disabled><br>
  <button type="button" id="run">Trim it!</button>
</div>

PS:为什么大多数人以前已经做过答案,但我为什么发布了答案?因为我在所有答案中都找到了“最好的”错误:所有人都使用了'+'而不是'*',所以' trim如果它们在开始和/或结束中,则必须删除字符,但是在其他情况下它会返回原始字符串。


0

扩展@leaf的答案,这是一个可以包含多个字符的代码:

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
}

0

我喜欢@ Pho3niX83的解决方案...

让我们用“单词”而不是“字符”扩展它...

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);
};




-1
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);
};

它只会删除一次出现,但不会修剪直到角色被完全修剪
KoalaBear

1
不要覆盖默认的字符串原型,否则稍后您会遇到麻烦。在其他地方创建自己的单独函数。
rooby

-2

试试这个方法:

var a = "anan güzel mi?";
if (a.endsWith("?"))   a = a.slice(0, -1);  
document.body.innerHTML = a;


1
为什么?这是做什么的?它是如何工作的?仅代码答案被认为是SO的低质量。说明您的答案,以便OP和任何将来的访问者可以从中学习。
不要惊慌
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.