文字列の前後の括弧を取る §
ここに文字列型の変数があるとします。
その変数に以下のような加工を行いたいと思います。
- 文字列の前後が括弧でくくられていたら、その括弧を取り去る
- 中間に出現した括弧は取らない
- 括弧は"()[]{}"とする。
たとえば、以下のような加工です。
- "{[山田太郎(一年)柔道部]}"→"山田太郎(一年)柔道部"
文字列の前後から指定した任意の文字を取り除くには? §
文字列のTrimで始まる名前を持つメソッドというと、文字列の前後の空白文字を取り除く機能を持っているというイメージが強くあります。実際に、引数なしで使えば空白文字を取り除きます。また、初期の頃はまさに【空白文字を取り除くためのメソッド】でした。他の言語の似た名前のメソッドは空白文字しか取り除かないかも知れません。
しかし、空白文字だけでは便利ではないので、現在は任意の文字を指定して文字列の前後から取り除く機能を持っています。
- TrimStart 文字列の前から指定した文字を取り除く
- TrimEnd 文字列の後から指定した文字を取り除く
- Trim 文字列の前後から指定した文字を取り除く
これを使えば、文字列の前後から指定された文字を取り除くのは簡単です。
取り除く文字が前と後で異なっていればTrimStartとTrimEndを使います。(例: src.TrimStart('(', '[', '{').TrimEnd(')', ']', '}');)
区別しなくて良ければ、Trimを使います。(例: src.Trim('(', '[', '{', ')', ']', '}');)
ちなみに、サンプルソースの【正攻法でガシガシやった場合】については初心者は理解しなくても構いません。これは使う必要のない書き方です。
中級者は動作を理解することに挑戦してみましょう。-1や+3の意味、++や--で何が起きているのか、この場合どんなケースのエラーチェックが省略されているのか、などを理解できればC#中級者です。
罠の数々 §
- Trim/TrimStart/TrimEndは、元の文字列は変更されない。加工済みの新しい文字列が返される
- TrimStart/TrimEndは連結して使っても良い。TrimStartの戻り値は文字列型なので、更にTrimEndを呼べるからだ
- 理論的には、TrimStartの後でTrimStartを呼ぶような使い方もできる。たとえば先頭の空白文字を取った上で"*"記号を取るならTrimStart().TrimStart('*')という使い方もあり得る
- 同様にTrimEndなどの複数利用もあり得るし、複数Trim系メソッドの混用もあり得る
- 実はこのコードは入力が"{[山田太郎(一年)]}"の場合、"山田太郎(一年)"という結果を期待しているのに、最後の括弧まで取って"山田太郎(一年"を返してしまう。これについて対策を取るには、【前から除去した文字に対応する文字を後ろから取る】という処理が必要になるがそれでも完全ではない。取りたくない括弧が前に来ていると、上手く処理できないからだ。完全な対策は難しいかも知れない。前後に括弧が来るとそれが取り除くべき括弧か残すべき括弧か曖昧になるケースがあるからだ。初心者はTrim系メソッドには制限事項があることを理解して活用しよう。中級者以上は、どこまで対策出来るか考えてみよう
参考リンク §
String.Trim メソッド
String.TrimStart メソッド
String.TrimEnd メソッド
リポジトリ §
https://github.com/autumn009/cshowto
Trim §
using System;
class Program
{
static void Main()
{
// 対象の文字列
var src = "{[山田太郎(一年)柔道部]}";
// 正攻法でガシガシやった場合
int from = 0;
int to = src.Length - 1;
for (; ; ) if (!"([{".Contains(src[from++])) break;
for (; ; ) if (!")]}".Contains(src[to--])) break;
var dst0 = src.Substring(from - 1, to - from + 3);
Console.WriteLine(dst0);
// 先頭と末尾を区別する場合
var dst1 = src.TrimStart('(', '[', '{').TrimEnd(')', ']', '}');
Console.WriteLine(dst1);
// 先頭と末尾を区別しなくても良い場合
var dst2 = src.Trim('(', '[', '{', ')', ']', '}');
Console.WriteLine(dst2);
}
}
実行結果
山田太郎(一年)柔道部
山田太郎(一年)柔道部
山田太郎(一年)柔道部