文字列から特定の文字を切り取る


120

のJavaScriptこれと同等のC#方法:

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

C#は、選択した文字を文字列の最初最後でのみトリミングします。

回答:


155

1行で十分です:

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
これはガベージコレクターにとって楽しいテストですが、クライアントにテストを依頼することはお勧めしません。
ソレンセン

18

次のような正規表現を使用できます。

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

17

この質問を最新に保つには:

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
ここでは正規表現が多すぎることを知っていますが、なぜこの特定の実装を選択するのですか?
ニコラスシャンクス2018年

2
私が個人的にそれを読みやすいと思うので、この実装。正規表現エンジン内の決定「ツリー」がはるかに大きいため、正規表現はありません。さらに、トリミングに使用される正規表現には、正規表現エンジン内のバックトラックにつながるクエリ文字が含まれているためです。そのようなエンジンは、パターンをバイトコードにコンパイルし、機械語命令に似ています。次に、エンジンはコードを実行し、命令間をジャンプします。命令が失敗すると、入力を照合する別の方法を見つけるためにバックトラックします。ergoはnecよりも多くのことを行っています。
ロビンF.

返信いただきありがとうございます。正規表現以外の方法でこれを選択する理由を説明していただきたいのですが、「読みやすい」以上のものを期待していたと思います。
Nicholas Shanks

1
@RobinF。あなたはfindIndex()とreverse()にループが含まれていないと思いますか?もう一度考えてみて。
アンドリュー

1
2つの注釈:トリミングされる文字のみを含む文字列は、まったくトリミングされません。もう1つのポイントは、spread演算子を使用して文字列を配列に分解すると、babelが混乱し[].concat(string)、目的の結果に変換されます。使用してArray.from(string)動作します。
ファビアン

14

目に優しい正規表現なしのバージョン:

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

端から文字が繰り返されないことが確実なユースケース。


非常に興味深い...したがって、splitは、分割された各区切り文字と等しい未定義の要素を返します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

より長い文字列を処理している場合、割り当てられた文字列の数を0または1に減らすことで、これは他のほとんどのオプションよりも優れているはずです。

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:いいえ、そうでもありません。これはデモです。コンソールに貼り付けると、結果が出力されるだけです。しかし、混乱する可能性があることを理解しているため、編集しました。
17

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には、求めているメソッドが組み込まれていません。ただし、JavaScriptでは、replaceを使用して文字列の内容を変更できます。

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

これは、|のすべての発生を置き換えます。何もありません。


を削除する方法はありますか?最初/最後だけですか?
fubo 2014年

私は実際にこの記事は、あなたの質問に速度に最もアップを取得すると思います:stackoverflow.com/questions/20196088/...
オーレ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トリムをドキュメントとするためにソーストリミングを行い、正確なコードを参照するには。

これはあなたの質問に正確な答えを提供しないことを知っていますが、他の人が役に立つと思うかもしれないので、そのような質問でライブラリへの参照を設定することは良いと思います。


1
@TamusJRoyceは同じではありません
gdbdable

@devi同意することしかできません。コメントありがとうございます。コミュニティでサポートされているツールを調べる良い答えです。
TamusJRoyce

1

このタスクを解決する最良の方法は(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彼らはSTART AND / OR ENDな場合は文字を削除する必要がありますが、それは他の場合には元の文字列を返します。


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からの解決策が好きです...

「char」ではなく「word」で拡張してみましょう...

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

1つのオカレンスのみが削除されますが、キャラクターが完全にトリミングされるまでトリミングされません
KoalaBear

1
デフォルトの文字列プロトタイプをオーバーライドしないでください。オーバーライドすると、後でトラブルが発生する可能性があります。別の場所に独自の関数を作成します。
rooby

-2

この方法を試してください:

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


1
どうして?これは何をしますか?それはどのように機能しますか?コードのみの回答は、SOでは低品質と見なされます。OPと今後の訪問者がOPから学習できるように、回答を説明してください。
パニックにならないでください。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.