ตัดแต่งอักขระเฉพาะจากสตริง


120

อะไรคือJavaScriptเทียบเท่านี้C#วิธีการ:

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

C # จดจ้องอักขระที่เลือกไว้ที่จุดเริ่มต้นและจุดสิ้นสุดของสตริงเท่านั้น!

คำตอบ:


156

หนึ่งบรรทัดก็เพียงพอ:

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

UPDATE:

หากคุณต้องการสรุปสิ่งนี้ให้เป็นฟังก์ชันคุณสามารถทำสิ่งต่อไปนี้:

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

เพื่อให้คำถามนี้เป็นปัจจุบัน:

นี่คือแนวทางที่ฉันเลือกจากฟังก์ชัน regex โดยใช้ตัวดำเนินการสเปรด 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
ฉันรู้ว่า regexes มีการใช้งานมากเกินไปที่นี่ แต่ทำไมคุณถึงเลือกใช้งานนี้
Nicholas Shanks

2
การใช้งานนี้เนื่องจากโดยส่วนตัวแล้วฉันพบว่ามันอ่านได้ดี ไม่มี regex เพียงเพราะการตัดสินใจ "ต้นไม้" ภายในเอนจิ้น regex นั้นใหญ่กว่ามาก และโดยเฉพาะอย่างยิ่งเนื่องจาก regexes ที่ใช้สำหรับการตัดแต่งมีอักขระคิวรีซึ่งนำไปสู่การย้อนกลับภายในเอนจิน regex เครื่องยนต์ดังกล่าวมักจะรวบรวมรูปแบบเป็นไบต์โค้ดคล้ายกับคำแนะนำของเครื่องจักร จากนั้นเครื่องยนต์จะรันโค้ดโดยกระโดดจากคำสั่งไปยังคำสั่ง เมื่อคำสั่งล้มเหลวระบบจะย้อนกลับเพื่อค้นหาวิธีอื่นในการจับคู่อินพุต ergo เกิดขึ้นมากมายกว่า nec
Robin F.

ขอบคุณสำหรับการตอบกลับแม้ว่าฉันต้องการให้คุณอธิบายว่าทำไมคุณถึงเลือกวิธีนี้มากกว่าวิธีอื่นที่ไม่ใช่ regex ในการทำเช่นนั้นฉันหวังว่าจะมีมากกว่านั้นเพียงแค่ "ฉันคิดว่ามันอ่านได้" ฉันคิดว่า
Nicholas Shanks

1
@RobinF คุณคิดว่า findIndex () และ reverse () ไม่มีลูป? คิดใหม่อีกครั้ง.
Andrew

1
คำอธิบายประกอบสองรายการ: สตริงที่มีเฉพาะอักขระที่จะตัดแต่งจะไม่ถูกตัดเลย อีกประเด็นคือ: การระเบิดสตริงลงในอาร์เรย์ด้วยตัวดำเนินการสเปรดจะทำให้บาเบลสับสนและเปลี่ยนเป็น[].concat(string)ผลลัพธ์ที่ไม่ต้องการ การใช้Array.from(string)จะทำงาน
Fabian

14

เวอร์ชัน regex-less ซึ่งง่ายต่อการมองเห็น:

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

สำหรับกรณีการใช้งานที่เราแน่ใจว่าไม่มีการสร้างตัวอักษรซ้ำจากขอบ


ค่อนข้างน่าสนใจ ... ดังนั้นการแยกจะส่งคืนองค์ประกอบที่ไม่ได้กำหนดให้เท่ากับตัวคั่นแต่ละตัวที่แยก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 ไม่มีฟังก์ชันในตัวตามที่คุณถาม อย่างไรก็ตามด้วยจาวาสคริปต์คุณสามารถใช้การแทนที่เพื่อเปลี่ยนเนื้อหาของสตริงของคุณ:

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

สิ่งนี้จะแทนที่การเกิดขึ้นทั้งหมดของ | โดยไม่มีอะไร


มีวิธีลบ | ตอนต้น / ตอนจบเท่านั้น?
fubo

ฉันคิดว่าโพสต์นี้จะทำให้คุณได้รับประโยชน์สูงสุดจากคำถามของคุณ: stackoverflow.com/questions/20196088/…
Ole 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

วิธีที่ดีที่สุดในการแก้ไขงานนี้คือ (คล้ายกับtrimฟังก์ชัน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: ทำไมฉันโพสต์คำตอบของฉันในเมื่อคนส่วนใหญ่เคยทำมาแล้ว? เนื่องจากฉันพบข้อผิดพลาด "ที่สุด" ในทุกคำตอบ: ทั้งหมดใช้เมตา "+" แทน "*" "สาเหตุ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 ...

ขอขยายความด้วย "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);
};


0
"|Howdy".replace(new RegExp("^\\|"),"");

(สังเกตการหนีคู่\\จำเป็นเพื่อให้มีเครื่องหมายทับเพียงครั้งเดียวในสตริงซึ่งจะนำไปสู่การหลบหนี|ในregExp )

อักขระเพียงไม่กี่ตัวเท่านั้นที่ต้องใช้ regExp-Escaping ในหมู่พวกเขาเป็นผู้ดำเนินการท่อ



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

เพียงแค่ลบเหตุการณ์เดียว แต่จะไม่ตัดออกจนกว่าตัวละครจะถูกตัดออก
จนหมด

1
อย่าแทนที่ต้นแบบสตริงเริ่มต้นมิฉะนั้นคุณจะต้องพบปัญหาในภายหลัง สร้างฟังก์ชันแยกของคุณเองที่อื่น
rooby

-2

ลองใช้วิธีนี้:

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


1
ทำไม? สิ่งนี้ทำอะไร? มันทำงานอย่างไร? คำตอบที่ใช้รหัสเท่านั้นถือว่ามีคุณภาพต่ำใน SO อธิบายคำตอบของคุณเพื่อให้ OP และผู้เยี่ยมชมในอนาคตสามารถเรียนรู้ได้
Don't Panic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.