Cắt ký tự cụ thể khỏi một chuỗi


120

Là gì JavaScript tương đương này C#Phương pháp:

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

C # chỉ cắt ký tự đã chọn ở đầucuối chuỗi!

Câu trả lời:


155

Một dòng là đủ:

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

Một giải pháp chung:

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

Nếu tôi hiểu rõ, bạn chỉ muốn xóa một ký tự cụ thể khi nó nằm ở đầu hoặc ở cuối chuỗi (ví dụ: ||fo||oo||||should be foo||oo). Bạn có thể tạo một hàm đặc biệt như sau:

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

Tôi đã thử nghiệm chức năng này với mã bên dưới:

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

3
Đây sẽ là một bài kiểm tra thú vị cho trình thu gom rác, nhưng tôi không khuyên bạn nên ép khách hàng của mình vào nó.
Sorensen

18

Bạn có thể sử dụng một biểu thức chính quy như:

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

CẬP NHẬT:

Nếu bạn muốn tổng quát hóa điều này thành một hàm, bạn có thể làm như sau:

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

để giữ cho câu hỏi này được cập nhật:

đây là một cách tiếp cận mà tôi sẽ chọn trên hàm regex bằng cách sử dụng toán tử lây lan 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);
}

Phiên bản cải tiến sau nhận xét của @fabian (chỉ có thể xử lý các chuỗi chứa cùng một ký tự)

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
Tôi biết regexes ở đây quá mức cần thiết, nhưng tại sao bạn lại chọn cách triển khai cụ thể này?
Nicholas Shanks

2
triển khai này bởi vì cá nhân tôi thấy nó có thể đọc được. không có regex đơn giản bởi vì "cây" quyết định trong các công cụ regex lớn hơn nhiều. và đặc biệt là vì các regex được sử dụng để cắt có chứa các ký tự truy vấn dẫn đến việc bẻ khóa ngược trong công cụ regex. những động cơ như vậy thường biên dịch mẫu thành mã byte, giống như lệnh máy. sau đó động cơ thực thi mã, chuyển từ lệnh này sang lệnh khác. khi một lệnh không thành công, nó sẽ theo dõi lại để tìm một cách khác để khớp với đầu vào. ergo nhiều hơn đang diễn ra hơn là chưa được phép.
Robin F.

Cảm ơn bạn đã trả lời, mặc dù tôi muốn bạn giải thích lý do tại sao bạn chọn điều này thay vì các cách thực hiện không phải regex khác - tôi đã hy vọng nhiều hơn rằng chỉ cần "Tôi thấy nó có thể đọc được", tôi cho là vậy.
Nicholas Shanks

1
@RobinF. bạn nghĩ rằng findIndex () và reverse () không chứa các vòng lặp? Nghĩ lại.
Andrew

1
Hai chú thích: Một chuỗi ký tự chỉ được cắt sẽ không bị cắt chút nào. Điểm khác là: Việc giải phóng chuỗi thành một mảng với toán tử spread sẽ gây nhầm lẫn cho babel và biến nó thành [].concat(string)kết quả không mong muốn. Sử dụng Array.from(string)sẽ hiệu quả.
Fabian

14

Một phiên bản ít regex dễ nhìn:

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

Đối với các trường hợp sử dụng mà chúng tôi chắc chắn rằng không có sự lặp lại của các ký tự ngoài rìa.


khá thú vị ... vì vậy tách trả về phần tử không xác định tương đương với mỗi dấu phân cách được táchconst 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

Nếu bạn đang xử lý các chuỗi dài hơn, tôi tin rằng điều này sẽ tốt hơn hầu hết các tùy chọn khác bằng cách giảm số lượng chuỗi được phân bổ xuống không hoặc một:

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'

Hoặc nếu bạn muốn cắt từ một tập hợp nhiều ký tự:

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'

CHỈNH SỬA: Để giải trí, hãy cắt các từ (thay vì các ký tự riêng lẻ)

// 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
Tôi thích giải pháp này vì nó thực sự hiệu quả hơn là chỉ ngắn gọn.
tekHedd

Tôi đồng ý rằng nó nên được ưu tiên. Thay thế một câu trả lời tôi đã đưa ra.
TamusJRoyce

9

Điều này có thể cắt một số ký tự cùng một lúc:

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: Không, không hẳn. Đó là một bản demo, nếu bạn dán nó vào một bảng điều khiển, nó sẽ chỉ in ra kết quả. Nhưng tôi hiểu nó có thể gây nhầm lẫn, vì vậy tôi đã chỉnh sửa nó.
marlar

2

Nếu bạn xác định các hàm này trong chương trình của mình, chuỗi của bạn sẽ có phiên bản nâng cấp trimcó thể cắt tất cả các ký tự đã cho:

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)

Nguồn

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


1

Theo hiểu biết của tôi, jQuery không có một hàm tích hợp như phương pháp mà bạn đang hỏi. Tuy nhiên, với javascript, bạn chỉ có thể sử dụng Replace để thay đổi nội dung chuỗi của mình:

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

Điều này sẽ thay thế tất cả các lần xuất hiện của | không có gì.


có cách nào để loại bỏ | chỉ ở đầu / cuối?
fubo

Tôi thực sự nghĩ rằng bài này sẽ giúp bạn có được nhiều nhất lên đến tốc độ trên câu hỏi của bạn: stackoverflow.com/questions/20196088/...
Ole Haugset

@fubo Chắc chắn ... Ném vào một cái $như thế này chỉ khi kết thúc: "||spam|||".replace(/\|+$/g, "")hoặc một cái ^tương tự chỉ khi bắt đầu:"||spam|||".replace(/^\|+/g, "")
ruffin 20/02/18

1

Cái này cắt tất cả các mê sảng đầu và cuối

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

Tôi khuyên bạn nên xem xét lodash và cách họ triển khai trimchức năng.

Xem Lodash Trim để biết tài liệu và nguồn để xem mã chính xác thực hiện việc cắt tỉa.

Tôi biết điều này không cung cấp câu trả lời chính xác cho câu hỏi của bạn, nhưng tôi nghĩ thật tốt khi đặt tham chiếu đến thư viện về câu hỏi như vậy vì những người khác có thể thấy nó hữu ích.


1
@TamusJRoyce không giống nhau
gdbdable

@devi Tôi chỉ có thể đồng ý. Cảm ơn bạn đã bình luận. câu trả lời hay khi tìm kiếm một công cụ được cộng đồng hỗ trợ.
TamusJRoyce

1

Cách tốt nhất để giải quyết tác vụ này là (tương tự với trimhàm PHP ):

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>

Tái bút: tại sao tôi đăng câu trả lời của mình, khi hầu hết mọi người đã làm nó trước đó? Bởi vì tôi đã tìm thấy sai lầm "tốt nhất" trong tất cả các câu trả lời ở đó: tất cả đều sử dụng meta '+' thay vì '*', 'nguyên nhân trimphải xóa các ký tự NẾU CHÚNG Ở BẮT ĐẦU VÀ / HOẶC KẾT THÚC, nhưng nó trả về chuỗi ban đầu trong trường hợp khác .


0

mở rộng về câu trả lời của @leaf, đây là câu trả lời có thể có nhiều ký tự:

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

Tôi thích giải pháp từ @ Pho3niX83 ...

Hãy mở rộng nó bằng "word" thay vì "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);
};




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

Nó chỉ loại bỏ một lần xuất hiện, nhưng không cắt cho đến khi nhân vật được cắt hoàn toàn
KoalaBear

1
Đừng ghi đè nguyên mẫu chuỗi mặc định nếu không bạn sẽ gặp rắc rối sau này. Tạo các chức năng riêng biệt của riêng bạn ở nơi khác.
rooby

-2

Hãy thử phương pháp này:

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


1
Tại sao? Điều này làm gì? Làm thế nào nó hoạt động? Câu trả lời chỉ có mã được coi là chất lượng thấp trên SO. Giải thích câu trả lời của bạn để OP và bất kỳ khách truy cập nào trong tương lai có thể học hỏi từ nó.
Don't Panic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.