简体   繁体   English

从字符串中修剪特定字符

[英]Trim specific character from a string

What's the JavaScript equivalent to this C# Method:什么是JavaScript相当于这个C#方法:

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

C# trims the selected character only at the beginning and end of the string! C# 仅在字符串的开头结尾修剪所选字符!

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).参数c应该是一个字符(长度为 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:为此, MightyPork建议将if替换为以下代码行:

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.这部分[-/\\\\^$*+?.()|[\\]{}]是正则表达式语法中的一组特殊字符, $&是代表匹配字符的占位符,表示replace函数转义特殊字符。 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 ).如果我理解得很好,您只想删除位于字符串开头或结尾的特定字符(例如: ||fo||oo||||应该变成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更新:对不同解决方案的性能很好奇,所以我在这里更新了一个基本的基准: https : //www.measurethat.net/Benchmarks/Show/12738/0/trimming-leadingtrailing-characters

Some interesting and unexpected results running under Chrome.在 Chrome 下运行的一些有趣和意外的结果。 https://www.measurethat.net/Benchmarks/ShowResult/182877 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');

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.对于我们确定边缘字符没有重复的用例。

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.这是我使用 ES6 扩展运算符选择 regex 函数的方法。

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

Improved version after @fabian 's comment (can handle strings containing the same character only) @fabian 评论后的改进版本(只能处理包含相同字符的字符串)

 function trimByChar1(string, character) { const arr = Array.from(string); const first = arr.findIndex(char => char !== character); const last = arr.reverse().findIndex(char => char !== character); return (first === -1 && last === -1) ? '' : string.substring(first, string.length - last); }

This can trim several characters at a time:这可以一次修剪多个字符:

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

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

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

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

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

For use in your own script and if you don't mind changing the prototype, this can be a convenient "hack":为了在您自己的脚本中使用,并且如果您不介意更改原型,这可以是一个方便的“hack”:

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

Since I use the trimChars function extensively in one of my scripts, I prefer this solution.因为我在我的一个脚本中广泛使用了 trimChars 函数,所以我更喜欢这个解决方案。 But there are potential issues with modifying an object's prototype .但是修改对象的原型存在潜在问题。

Regex seems a bit too complex for a simple problem like Trim? 对于像Trim这样的简单问题,正则表达式似乎太复杂了?

C# C#

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

Javascript, x.TrimLeft('|') example - simple (but trims only single character) Javascript,x.TrimLeft('|')示例-简单(但仅修剪单个字符)

 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) Javascript完整示例(感谢@Tobo答案和@rooby建议)

 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. 我对trimStart和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. 注意:这是es6特定的。 Some of this may be implemented for you in es2019. 其中一些可能会在es2019中为您实现。

If you define these functions in your program, your strings will have an upgraded version of trim that can trim all given characters:如果你在你的程序中定义了这些函数,你的字符串将有一个升级版的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)

Source来源

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

const trim = (str, char) => {
    let i = 0;
    let j = str.length-1;
    while (str[i] === char) i++;
    while (str[j] === char) j--;
    return str.slice(i,j+1);
}
console.log(trim('|f|oo|', '|')); // f|oo

Non-regex solution.非正则表达式解决方案。 Two pointers: i (beginning) & j (end).两个指针: i (开始)和j (结束)。 Only move pointers if they match char and stop when they don't.仅在匹配 char 时移动指针,不匹配时停止。 Return remaining string.返回剩余的字符串。

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

I would suggest looking at lodash and how they implemented the trim function.我建议查看 lodash 以及他们如何实现trim功能。

See Lodash Trim for the documentation and the source to see the exact code that does the trimming.有关文档和 代码,请参阅Lodash Trim以查看进行修剪的确切代码。

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.我知道这并没有提供您的问题的确切答案,但我认为在这样的问题上设置对图书馆的引用是很好的,因为其他人可能会发现它很有用。

The best way to resolve this task is (similar with PHP trim function):解决此任务的最佳方法是(类似于 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: why i posted my answer, when most people already done it before? PS:为什么我发布了我的答案,而大多数人以前已经做过了? Because i found "the best" mistake in all of there answers: all used the '+' meta instead of '*', 'cause trim must remove chars IF THEY ARE IN START AND/OR END, but it return original string in else case.因为我在所有答案中发现了“最好的”错误:都使用了 '+' 元而不是 '*',因为如果它们在开始和/或结束中, trim必须删除字符,但它在其他地方返回原始字符串案件。

expanding on @leaf 's answer, here's one that can take multiple characters:扩展@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
}

I like the solution from @Pho3niX83...我喜欢@Pho3niX83 的解决方案...

Let's extend it with "word" instead of "char"...让我们用“word”而不是“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);
};
function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}
"|Howdy".replace(new RegExp("^\\|"),"");

(note the double escaping. \\\\ needed, to have an actually single slash in the string , that then leads to escaping of | in the regExp ). (注意双重转义。 \\\\需要,在字符串中有一个实际的单斜杠,然后导致在regExp 中转义| )。

Only few characters need regExp-Escaping.只有少数字符需要 regExp-Escaping。 , among them the pipe operator. ,其中有管道操作员。

 const special = ':;"<>?/!`~@#$%^&*()+=-_ '.split(""); const trim = (input) => { const inTrim = (str) => { const spStr = str.split(""); let deleteTill = 0; let startChar = spStr[deleteTill]; while (special.some((s) => s === startChar)) { deleteTill++; if (deleteTill <= spStr.length) { startChar = spStr[deleteTill]; } else { deleteTill--; break; } } spStr.splice(0, deleteTill); return spStr.join(""); }; input = inTrim(input); input = inTrim(input.split("").reverse().join("")).split("").reverse().join(""); return input; }; alert(trim('@#This is what I use$%'));

Another version to use regular expression.另一个使用正则表达式的版本。

No or( | ) used and no global( g ) used.没有使用 or( | ) 也没有使用 global( g )。

 function escapeRegexp(s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } function trimSpecific(value, find) { const find2 = escapeRegexp(find); return value.replace(new RegExp(`^[${find2}]*(.*?)[${find2}]*$`), '$1') } console.log(trimSpecific('"a"b"', '"') === 'a"b'); console.log(trimSpecific('""ab"""', '"') === 'ab'); console.log(trimSpecific('"', '"') === ''); console.log(trimSpecific('"a', '"') === 'a'); console.log(trimSpecific('a"', '"') === 'a'); console.log(trimSpecific('[a]', '[]') === 'a'); console.log(trimSpecific('{[a]}', '[{}]') === 'a');

To my knowledge, jQuery doesnt have a built in function the method your are asking about.据我所知,jQuery 没有您所询问的方法的内置函数。 With javascript however, you can just use replace to change the content of your string:但是,使用 javascript,您可以只使用替换来更改字符串的内容:

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

This will replace all occurences of |这将替换所有出现的 | with nothing.一无所有。

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

尝试:

console.log(x.replace(/\|/g,''));

Try this method:试试这个方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM