簡體   English   中英

從字符串中修剪特定字符

[英]Trim specific character from a string

什么是JavaScript相當於這個C#方法:

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

C# 僅在字符串的開頭結尾修剪所選字符!

一行就夠了:

 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 = "\\\\^"; 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)); }

參數c應該是一個字符(長度為 1 的字符串)。

正如評論中提到的,支持多個字符可能很有用,因為例如修剪多個類似空格的字符是很常見的。 為此, MightyPork建議將if替換為以下代碼行:

c = c.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');

這部分[-/\\\\^$*+?.()|[\\]{}]是正則表達式語法中的一組特殊字符, $&是代表匹配字符的占位符,表示replace函數轉義特殊字符。 在瀏覽器控制台中嘗試:

> "{[hello]}".replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
"\{\[hello\]\}"

如果我理解得很好,您只想刪除位於字符串開頭或結尾的特定字符(例如: ||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, "|") + "'" );

更新:對不同解決方案的性能很好奇,所以我在這里更新了一個基本的基准: https : //www.measurethat.net/Benchmarks/Show/12738/0/trimming-leadingtrailing-characters

在 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        |
+-----------------------------------+-----------------------+

請注意; 僅對單個測試字符串(需要修剪的前導和尾隨字符)進行測試。 此外,該基准測試僅給出原始速度的指示; 其他因素(如內存使用情況)也很重要。


如果您正在處理更長的字符串,我相信通過將分配的字符串數量減少到零或一,這應該優於大多數其他選項:

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

一個簡單的無正則表達式版本:

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

對於我們確定邊緣字符沒有重復的用例。

您可以使用正則表達式,例如:

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

保持這個問題是最新的:

這是我使用 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);
}

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

這可以一次修剪多個字符:

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

為了在您自己的腳本中使用,並且如果您不介意更改原型,這可以是一個方便的“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

因為我在我的一個腳本中廣泛使用了 trimChars 函數,所以我更喜歡這個解決方案。 但是修改對象的原型存在潛在問題。

對於像Trim這樣的簡單問題,正則表達式似乎太復雜了?

C#

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

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完整示例(感謝@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();"); 

我對trimStart和trimEnd有點懶。 找到每邊需要修整多少會更有效。 然后只調用一次子字符串。 但是希望您能想到這個,對您有所幫助!

注意:這是es6特定的。 其中一些可能會在es2019中為您實現。

如果你在你的程序中定義了這些函數,你的字符串將有一個升級版的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/

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

非正則表達式解決方案。 兩個指針: i (開始)和j (結束)。 僅在匹配 char 時移動指針,不匹配時停止。 返回剩余的字符串。

這個修剪所有前導和尾隨定界符

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

我建議查看 lodash 以及他們如何實現trim功能。

有關文檔和 代碼,請參閱Lodash Trim以查看進行修剪的確切代碼。

我知道這並沒有提供您的問題的確切答案,但我認為在這樣的問題上設置對圖書館的引用是很好的,因為其他人可能會發現它很有用。

解決此任務的最佳方法是(類似於 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必須刪除字符,但它在其他地方返回原始字符串案件。

擴展@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
}

我喜歡@Pho3niX83 的解決方案...

讓我們用“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("^\\|"),"");

(注意雙重轉義。 \\\\需要,在字符串中有一個實際的單斜杠,然后導致在regExp 中轉義| )。

只有少數字符需要 regExp-Escaping。 ,其中有管道操作員。

 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$%'));

另一個使用正則表達式的版本。

沒有使用 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');

據我所知,jQuery 沒有您所詢問的方法的內置函數。 但是,使用 javascript,您可以只使用替換來更改字符串的內容:

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

這將替換所有出現的 | 一無所有。

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

試試這個方法:

 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