7

.NET String クラスの拡張メソッドを書きたいと思います。Split メソッドの特別なバリエーションにしたいと思います。これは、エスケープ文字がセパレーターの前に使用されている場合に文字列が分割されないようにするためにエスケープ文字を使用するものです。

これを書く最良の方法は何ですか?私はそれにアプローチするための最良の非正規表現方法に興味があります。
みたいなサイン入りのやつ…

public static string[] Split(this string input, string separator, char escapeCharacter)
{
   // ...
}

更新: コメントの1つで出てきたので、エスケープ...

C# で非特殊文字をエスケープすると、エラー - CS1009: 認識されないエスケープ シーケンスが発生します。

IE JScript では、エスケープ文字が破棄されます。\u を試してから「予期される 16 進数」エラーが発生しない限り。Firefox をテストしましたが、同じ動作をします。

私は、このメソッドがかなり寛容で、JavaScript モデルに従っていることを望みます。非区切り文字でエスケープする場合は、エスケープ文字を「親切に」削除する必要があります。

4

10 に答える 10

12

どうですか:

public static IEnumerable<string> Split(this string input, 
                                        string separator,
                                        char escapeCharacter)
{
    int startOfSegment = 0;
    int index = 0;
    while (index < input.Length)
    {
        index = input.IndexOf(separator, index);
        if (index > 0 && input[index-1] == escapeCharacter)
        {
            index += separator.Length;
            continue;
        }
        if (index == -1)
        {
            break;
        }
        yield return input.Substring(startOfSegment, index-startOfSegment);
        index += separator.Length;
        startOfSegment = index;
    }
    yield return input.Substring(startOfSegment);
}

それは(いくつかの簡単なテスト文字列で)うまくいくようですが、エスケープ文字は削除されません-それはあなたの正確な状況に依存すると思います.

于 2009-03-11T14:44:43.937 に答える
7

これは少しクリーンアップする必要がありますが、本質的にはこれで終わりです....

List<string> output = new List<string>();
for(int i=0; i<input.length; ++i)
{
    if (input[i] == separator && (i==0 || input[i-1] != escapeChar))
    {
        output.Add(input.substring(j, i-j);
        j=i;
    }
}

return output.ToArray();
于 2009-03-11T14:41:21.760 に答える
4

私の最初の観察は、単一の文字を使用して文字列をエスケープするのは難しいかもしれないので、区切り文字は文字列ではなく文字であるべきだということです.エスケープ文字は次の文字列のどのくらいをカバーしていますか? それ以外は、@James Curranの答えは、私がそれを処理する方法とほぼ同じです-ただし、彼が言うように、クリーンアップが必要です。たとえば、ループ初期化子で j を 0 に初期化します。null 入力の処理方法などを理解する。

おそらく、StringSplitOptions もサポートし、コレクションで空の文字列を返すかどうかを指定する必要があります。

于 2009-03-11T14:46:21.873 に答える
4

エスケープ文字を削除する場合の解決策は次のとおりです。

public static IEnumerable<string> Split(this string input, 
                                        string separator, 
                                        char escapeCharacter) {
    string[] splitted = input.Split(new[] { separator });
    StringBuilder sb = null;

    foreach (string subString in splitted) {
        if (subString.EndsWith(escapeCharacter.ToString())) {
            if (sb == null)
                sb = new StringBuilder();
            sb.Append(subString, 0, subString.Length - 1);
        } else {
            if (sb == null)
                yield return subString;
            else {
                sb.Append(subString);
                yield return sb.ToString();
                sb = null;
            }
        }
    }
    if (sb != null)
        yield return sb.ToString();
}
于 2009-03-11T15:31:34.463 に答える
3
public static string[] Split(this string input, string separator, char escapeCharacter)
{
    Guid g = Guid.NewGuid();
    input = input.Replace(escapeCharacter.ToString() + separator, g.ToString());
    string[] result = input.Split(new string []{separator}, StringSplitOptions.None);
    for (int i = 0; i < result.Length; i++)
    {
        result[i] = result[i].Replace(g.ToString(), escapeCharacter.ToString() + separator);
    }

    return result;
}

おそらく最善の方法ではありませんが、別の方法です。基本的に、エスケープ + セパレーターのシーケンスが見つかった場合はどこでも、それを GUID に置き換えます (ここでは他のランダムながらくたを使用できますが、問題ではありません)。次に、組み込みの分割機能を使用します。次に、配列の各要素の GUID をエスケープ + セパレータに置き換えます。

于 2009-03-11T14:52:53.403 に答える
1

個人的には、string.Split using Reflector...InternalSplitOmitEmptyEntries便利そうです ;-)

于 2009-03-11T14:51:24.403 に答える
1

署名が正しくありません。文字列配列を返す必要があります

WARNIG NEVER USED EXTENSION ですので、多少の間違いはご容赦ください ;)

public static List<String> Split(this string input, string separator, char escapeCharacter)
{
    String word = "";
    List<String> result = new List<string>();
    for (int i = 0; i < input.Length; i++)
    {
//can also use switch
        if (input[i] == escapeCharacter)
        {
            break;
        }
        else if (input[i] == separator)
        {
            result.Add(word);
            word = "";
        }
        else
        {
            word += input[i];    
        }
    }
    return result;
}
于 2009-03-11T14:44:34.717 に答える
0
public string RemoveMultipleDelimiters(string sSingleLine)
{
    string sMultipleDelimitersLine = "";
    string sMultipleDelimitersLine1 = "";
    int iDelimeterPosition = -1;
    iDelimeterPosition = sSingleLine.IndexOf('>');
    iDelimeterPosition = sSingleLine.IndexOf('>', iDelimeterPosition + 1);
    if (iDelimeterPosition > -1)
    {
        sMultipleDelimitersLine = sSingleLine.Substring(0, iDelimeterPosition - 1);
        sMultipleDelimitersLine1 = sSingleLine.Substring(sSingleLine.IndexOf('>', iDelimeterPosition) - 1);
        sMultipleDelimitersLine1 = sMultipleDelimitersLine1.Replace('>', '*');
        sSingleLine = sMultipleDelimitersLine + sMultipleDelimitersLine1;
    }
    return sSingleLine;
}
于 2009-07-28T13:16:58.823 に答える