Pangkas karakter tertentu dari string


120

Apa persamaan JavaScript dengan C#Metode ini :

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

C # memangkas karakter yang dipilih hanya di awal dan akhir string!

Jawaban:


155

Satu baris sudah cukup:

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

Solusi umum:

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

Jika saya mengerti dengan baik, Anda ingin menghapus karakter tertentu hanya jika di awal atau di akhir string (ex: ||fo||oo||||harus menjadi foo||oo). Anda dapat membuat fungsi ad hoc sebagai berikut:

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

Saya menguji fungsi ini dengan kode di bawah ini:

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

3
Ini akan menjadi tes yang menyenangkan bagi pengumpul sampah, tapi saya tidak akan merekomendasikan klien Anda untuk itu.
Sorensen

18

Anda dapat menggunakan ekspresi reguler seperti:

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

MEMPERBARUI:

Jika Anda ingin menggeneralisasi ini menjadi suatu fungsi, Anda dapat melakukan hal berikut:

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

untuk terus memperbarui pertanyaan ini:

di sini adalah pendekatan yang akan saya pilih daripada fungsi regex menggunakan operator spread 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);
}

Versi yang ditingkatkan setelah komentar @fabian (hanya dapat menangani string yang berisi karakter yang sama)

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
Saya tahu regex berlebihan di sini, tetapi mengapa Anda memilih implementasi khusus ini?
Nicholas Shanks

2
implementasi ini karena saya pribadi merasa terbaca dengan baik. tidak ada regex hanya karena keputusan "pohon" dalam mesin regex jauh lebih besar. dan terutama karena ekspresi reguler yang digunakan untuk pemangkasan berisi karakter kueri yang menyebabkan kemunduran dalam mesin regex. mesin seperti itu sering mengkompilasi pola menjadi kode-byte, menyerupai instruksi mesin. mesin kemudian menjalankan kode, melompat dari instruksi ke instruksi. ketika sebuah instruksi gagal, itu kemudian melacak kembali untuk menemukan cara lain untuk mencocokkan input. ergo lebih banyak terjadi daripada nec.
Robin F.

Terima kasih telah membalas, meskipun saya ingin Anda menjelaskan mengapa Anda memilih ini daripada cara non-regex lain untuk melakukannya - saya berharap lebih dari sekadar "Saya merasa dapat dibaca", saya kira.
Nicholas Shanks

1
@Robin. menurut Anda findIndex () dan reverse () tidak berisi loop? Pikirkan lagi.
Andrew

1
Dua anotasi: String yang hanya berisi karakter yang akan dipotong tidak akan dipangkas sama sekali. Poin lainnya adalah: Meledakkan string menjadi array dengan operator penyebaran akan membingungkan babel dan mengubahnya menjadi hasil [].concat(string)yang tidak diinginkan. Menggunakan Array.from(string)akan berhasil.
Fabian

14

Versi regex-less yang enak dilihat:

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

Untuk kasus penggunaan di mana kami yakin bahwa tidak ada pengulangan karakter di luar batas.


cukup menarik ... jadi split mengembalikan elemen yang tidak ditentukan untuk sama dengan setiap pembatas yang dibagiconst 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

Jika Anda berurusan dengan string yang lebih panjang, saya yakin ini akan mengungguli sebagian besar opsi lain dengan mengurangi jumlah string yang dialokasikan menjadi nol atau satu:

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'

Atau jika Anda ingin memotong dari sekumpulan beberapa karakter:

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: Untuk bersenang-senang, potong kata-kata (bukan karakter individu)

// 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
Saya lebih suka solusi ini karena sebenarnya efisien, daripada hanya singkat.
tekHedd

Saya setuju itu harus lebih disukai. Menggantikan jawaban yang telah saya berikan.
TamusJRoyce

9

Ini dapat memangkas beberapa karakter sekaligus:

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: Tidak, tidak juga. Ini demo, jika Anda menempelkannya di konsol, itu hanya akan mencetak hasilnya. Tapi saya mengerti ini bisa membingungkan, jadi saya telah mengeditnya.
marlar

2

Jika Anda menentukan fungsi-fungsi ini dalam program Anda, string Anda akan memiliki versi yang ditingkatkan trimyang dapat memangkas semua karakter yang diberikan:

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)

Sumber

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


1

Sepengetahuan saya, jQuery tidak memiliki fungsi bawaan seperti yang Anda tanyakan. Namun dengan javascript, Anda bisa menggunakan replace untuk mengubah konten string Anda:

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

Ini akan menggantikan semua kemunculan | dengan apa-apa.


apakah ada cara untuk menghapus | hanya di awal / akhir?
fubo

Saya benar-benar berpikir posting ini akan memberi Anda hasil maksimal untuk pertanyaan Anda: stackoverflow.com/questions/20196088/…
Ole Haugset

@fubo Tentu ... Lemparkan $seperti ini hanya di akhir: "||spam|||".replace(/\|+$/g, "")atau ^seperti ini hanya di awal:"||spam|||".replace(/^\|+/g, "")
ruffin

1

Yang ini memotong semua pembatas depan dan belakang

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

Saya akan menyarankan untuk melihat lodash dan bagaimana mereka mengimplementasikan trimfungsinya.

Lihat Lodash Trim untuk dokumentasi dan sumber untuk melihat kode persis yang melakukan pemangkasan.

Saya tahu ini tidak memberikan jawaban yang tepat untuk pertanyaan Anda, tetapi saya pikir ada baiknya untuk menetapkan referensi ke perpustakaan tentang pertanyaan seperti itu karena orang lain mungkin menganggapnya berguna.


1
@TamusJRoyce tidak sama
gdbdable

@devi Saya hanya bisa setuju. terima kasih atas komentarnya jawaban yang bagus melihat ke alat yang didukung komunitas.
TamusJRoyce

1

Cara terbaik untuk menyelesaikan tugas ini adalah (mirip dengan trimfungsi 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>

PS: Mengapa saya memposting jawaban saya, padahal kebanyakan orang sudah melakukannya sebelumnya? Karena saya menemukan kesalahan "terbaik" di semua jawaban yang ada: semua menggunakan meta '+', bukan '*', 'karena trimharus menghapus karakter JIKA MEREKA DI MULAI DAN / ATAU AKHIR, tetapi mengembalikan string asli dalam kasus lain .


0

memperluas jawaban @leaf, berikut salah satu yang dapat mengambil banyak karakter:

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

Saya suka solusi dari @ Pho3niX83 ...

Mari kita perpanjang dengan "kata" daripada "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);
};

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



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

Ini hanya menghapus satu kejadian, tetapi tidak memangkas sampai karakter sepenuhnya dipangkas
KoalaBear

1
Jangan menimpa prototipe string default atau Anda akan meminta masalah nanti. Buat fungsi terpisah Anda sendiri di tempat lain.
rooby

-2

Coba metode ini:

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


1
Mengapa? Apa fungsinya? Bagaimana cara kerjanya? Jawaban kode-saja dianggap berkualitas rendah pada SO. Jelaskan jawaban Anda agar OP dan setiap pengunjung di masa mendatang dapat belajar darinya.
Jangan Panik
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.