DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

文字列の前後に付いている余計な文字を削除する

ここでは、文字列(String)の先頭と末尾に付いている特定の文字を削除する方法を紹介します。例えば、文字列の末尾に付いている改行文字を削除したり、文字列の先頭に付いている余計な空白文字を削除したりするときに役に立ちます。

なお、文字列全体から、指定した文字を削除する方法は、「文字列から指定した文字を削除する」をご覧ください。

String.Trimで空白文字を削除する

文字列の前後に付いているスペース文字や、改行文字などの空白文字(ホワイトスペース文字、whitespace characters)をすべて削除したい場合は、StringクラスのTrimメソッドを使います。また、文字列の先頭に付いている空白文字だけを削除するにはTrimStart、文字列の末尾に付いている空白文字だけを削除するにはTrimEndメソッドを使います。

これらのメソッドは空白文字を削除した文字列を返すだけで、メソッドを呼び出した文字列そのものに変化を与えるわけではありません。

これらのメソッドが削除する文字は、半角、全角のスペース文字、タブ文字、改行文字(キャリッジリターン、ラインフィード)などです。もっと正確に言えば、Char.IsWhiteSpaceメソッドがTrueを返す文字です。詳しくは、MSDNをご覧ください。

補足:.NET Framework 3.5 SP1以前とそれより後では、削除する文字が若干異なります。詳しくは、MSDNの「String.Trim メソッド」をご覧ください。

以下に、Trim、TrimStart、TrimEndメソッドを使用した例を示します。

VB.NET
コードを隠すコードを選択
'「こんにちは。」の前にタブ文字、半角スペース、全角スペースが、
'後ろにキャリッジリターンとラインフィードが付いている
Dim s As String = vbTab & "  こんにちは。" & vbCrLf

'前後の空白文字を削除する
Dim s1 As String = s.Trim()
's1は、「こんにちは。」

'先頭の空白文字を削除する
Dim s2 As String = s.TrimStart()

'末尾の空白文字を削除する
Dim s3 As String = s.TrimEnd()
C#
コードを隠すコードを選択
//「Visual Basic」の前にタブ文字、半角スペース、全角スペースが、
//後ろにキャリッジリターンとラインフィードが付いている
string s = "\t  Visual Basic\r\n";

//前後の空白文字を削除する
string s1 = s.Trim();
//s1は、「Visual Basic」

//先頭の空白文字を削除する
string s2 = s.TrimStart();

//末尾の空白文字を削除する
string s3 = s.TrimEnd();
補足:VB.NETでは、Trim、TrimStart、TrimEndメソッドの代わりに、Trim関数LTrim関数RTrim関数を使うこともできます。ただしこれらの関数は半角スペースと全角スペースしか削除しません。

指定した文字を削除する

Trim、TrimStart、TrimEndメソッドは、決められた空白文字を削除するだけでなく、指定した文字を削除することもできます。この時削除されるのは指定された文字だけで、それ以外の文字は空白文字であっても削除されません。

以下の例では、文字列の前後に付いたピリオド、コンマ、セミコロン、コロンを削除しています。

VB.NET
コードを隠すコードを選択
Dim s As String = ".,DOBON.NET:;"

'前後の".,:;"を削除する
Dim s1 As String = s.Trim("."c, ","c, ":"c, ";"c)
'または、
Dim s2 As String = s.Trim(New Char() {"."c, ","c, ":"c, ";"c})
'結果は、「DOBON.NET」
C#
コードを隠すコードを選択
string s = ".,DOBON.NET:;";

//前後の".,:;"を削除する
string s1 = s.Trim('.', ',', ':', ';');
//または、
string s2 = s.Trim(new char[] { '.', ',', ':', ';' });
//結果は、「DOBON.NET」

正規表現を使用した方法

String.Trim以外では、正規表現を使う方法が考えられます。正規表現を使えばより複雑な条件で文字を削除することができますが、パフォーマンスは劣ります。正規表現について詳しくは、「正規表現を使って文字列を置換する」をご覧ください。

以下に、正規表現を使って文字列の前についた半角スペースとタブ文字、後ろに付いたキャリッジリターンとラインフィードを削除する例を示します。

VB.NET
コードを隠すコードを選択
Dim s As String = vbTab & "   DOBON.NET" & vbCr & vbLf

'先頭の半角スペースとタブ文字を削除する
s = System.Text.RegularExpressions.Regex.Replace(s, "^[ \t]+", "")

'末尾のキャリッジリターンとラインフィードを削除する
s = System.Text.RegularExpressions.Regex.Replace(s, "[\r\n]+$", "")
C#
コードを隠すコードを選択
string s = "\t   DOBON.NET\r\n";

//先頭の半角スペースとタブ文字を削除する
s = System.Text.RegularExpressions.Regex.Replace(
    s, @"^[ \t]+", "");

//末尾のキャリッジリターンとラインフィードを削除する
s = System.Text.RegularExpressions.Regex.Replace(
    s, @"[\r\n]+$", "");

String.Trimのパフォーマンス

例えば、空白文字が文字列の後ろにだけ付いており、前には絶対に付いていないことが分かっている時は、TrimよりもTrimEndを使った方が効率的なような気がします。また、文字列の前後に付いている空白文字が必ずある文字だと分かっている時は、パラメータを指定しないでTrimを呼び出すよりも、その文字を指定してTrimメソッドを呼び出した方が良さそうな気もします。さらに、削除する文字数が分かっているならば、Substringメソッドを使った方が速いような気もします。

そこで、実際はどうなのか、以下のようなコードで試してみました。

VB.NET
コードを隠すコードを選択
Dim loopCount As Integer = 1000000
Dim s As String = New String("0"c, 10000) & New String(vbLf, 1)

'Trimのみ
Dim s1 As String = ""
Dim sw1 As New System.Diagnostics.Stopwatch()
sw1.Start()
For i As Integer = 0 To loopCount - 1
    s1 = s.Trim()
Next
sw1.Stop()
Console.WriteLine("Trim(): {0}", sw1.ElapsedTicks)

'TrimEnd
Dim s2 As String = ""
Dim sw2 As New System.Diagnostics.Stopwatch()
sw2.Start()
For i As Integer = 0 To loopCount - 1
    s2 = s.TrimEnd()
Next
sw2.Stop()
Console.WriteLine("TrimEnd(): {0}", sw2.ElapsedTicks)

'削除する文字を指定してTrim
Dim s3 As String = ""
Dim sw3 As New System.Diagnostics.Stopwatch()
sw3.Start()
For i As Integer = 0 To loopCount - 1
    s3 = s.Trim(vbLf)
Next
sw3.Stop()
Console.WriteLine("Trim('\n'): {0}", sw3.ElapsedTicks)

'Substring
Dim s4 As String = ""
Dim sw4 As New System.Diagnostics.Stopwatch()
sw4.Start()
For i As Integer = 0 To loopCount - 1
    s4 = s.Substring(0, s.Length - 1)
Next
sw4.Stop()
Console.WriteLine("Substring: {0}", sw4.ElapsedTicks)
C#
コードを隠すコードを選択
int loopCount = 1000000;
string s = new string('0', 10000) + new string('\n', 1);

//Trimのみ
string s1 = "";
System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch();
sw1.Start();
for (int i = 0; i < loopCount; i++)
{
    s1 = s.Trim();
}
sw1.Stop();
Console.WriteLine("Trim(): {0}", sw1.ElapsedTicks);

//TrimEnd
string s2 = "";
System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch();
sw2.Start();
for (int i = 0; i < loopCount; i++)
{
    s2 = s.TrimEnd();
}
sw2.Stop();
Console.WriteLine("TrimEnd(): {0}", sw2.ElapsedTicks);

//削除する文字を指定してTrim
string s3 = "";
System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch();
sw3.Start();
for (int i = 0; i < loopCount; i++)
{
    s3 = s.Trim('\n');
}
sw3.Stop();
Console.WriteLine("Trim('\\n'): {0}", sw3.ElapsedTicks);

//Substring
string s4 = "";
System.Diagnostics.Stopwatch sw4 = new System.Diagnostics.Stopwatch();
sw4.Start();
for (int i = 0; i < loopCount; i++)
{
    s4 = s.Substring(0, s.Length - 1);
}
sw4.Stop();
Console.WriteLine("Substring: {0}", sw4.ElapsedTicks);

私が.NET Framework 4.0で試したところでは、例えば以下のような結果が出力されました。意外とTrimをパラメータなしで呼び出すのが速いことが分かりました。

Trim(): 11131598
TrimEnd(): 11700690
Trim('\n'): 11580390
Substring: 11157845

次に、削除する文字が多いときはどうなるかと思い、文字列の最後に付けるラインフィード文字を100個に増やして試してみました。すると今度はSubstringが明らかに速く、パラメータを指定したTrimが、パラメータを指定しなかったTrimより若干速いという結果になりました。

Trim(): 12447101
TrimEnd(): 12747048
Trim('\n'): 12262099
Substring: 10909820

ただしこれらの結果はあくまで私の簡単な試行によるものですので、正確ではないかもしれないことをご了承ください。

  • 履歴:
  • 2013/5/30 「正規表現を使用した方法」に例を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。