Как я могу разбить эту строку в массив? - PullRequest
5 голосов
/ 27 января 2009

Моя строка выглядит следующим образом:

smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;

Мне нужно обратно:

smtp:jblack@test.com
SMTP:jb@test.com
X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;

Проблема в том, что точки с запятой разделяют адреса, а также часть адреса X400. Кто-нибудь может подсказать, как лучше разделить это?

PS Я должен упомянуть, что порядок отличается, поэтому он может быть:

X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;;smtp:jblack@test.com;SMTP:jb@test.com

Может быть более 3 адресов, 4, 5 .. 10 и т. Д., Включая адрес X500, однако все они начинаются с smtp: SMTP: X400 или X500.

Ответы [ 12 ]

9 голосов
/ 27 января 2009

РЕДАКТИРОВАТЬ: с обновленной информацией, этот ответ, безусловно, не сработает - но он все еще потенциально полезен, поэтому я оставлю его здесь.

У вас всегда будет три части, и вы просто хотите разделить первые две точки с запятой?

Если это так, просто используйте перегрузку Split, которая позволяет указать количество возвращаемых подстрок:

string[] bits = text.Split(new char[]{';'}, 3);
4 голосов
/ 27 января 2009

Могу я предложить построить регулярное выражение

(smtp|SMTP|X400|X500):((?!smtp:|SMTP:|X400:|X500:).)*;?

или без протокола

.*?:((?![^:;]*:).)*;?

другими словами, найдите все, что начинается с одного из ваших протоколов. Подходим двоеточие. Затем продолжайте сопоставлять символы, если вы не соответствуете ни одному из ваших протоколов. Завершите точкой с запятой (опционально).

Затем вы можете проанализировать список совпадений, разделив его на ':', и вы получите свои протоколы. Кроме того, если вы хотите добавить протоколы, просто добавьте их в список.

Вероятно, однако, вы захотите указать все это без учета регистра и перечислить протоколы только в верхнем или нижнем регистре.

Для версии без протокола все равно, как называются протоколы. Он просто находит их все одинаковыми, сопоставляя все до, но исключая строку, за которой следует двоеточие или точка с запятой.

3 голосов
/ 27 января 2009

Разделить по следующей схеме регулярных выражений

string[] items = System.Text.RegularExpressions.Split(text, ";(?=\w+:)");

РЕДАКТИРОВАТЬ: лучше можно принимать больше специальных символов в имени протокола.

string[] items = System.Text.RegularExpressions.Split(text, ";(?=[^;:]+:)");
1 голос
/ 27 января 2009

Вы всегда можете разделить двоеточие и использовать небольшую логику, чтобы получить ключ и значение.

string[] bits = text.Split(':');
List<string> values = new List<string>();
for (int i = 1; i < bits.Length; i++)
{
    string value = bits[i].Contains(';') ? bits[i].Substring(0, bits[i].LastIndexOf(';') + 1) : bits[i];
    string key = bits[i - 1].Contains(';') ? bits[i - 1].Substring(bits[i - 1].LastIndexOf(';') + 1) : bits[i - 1];
    values.Add(String.Concat(key, ":", value));
}

Протестировал его с обоими образцами, и он отлично работает.

1 голос
/ 27 января 2009

Не самый быстрый, если вы делаете это много, но это будет работать для всех случаев, я считаю.

        string input1 = "smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";
        string input2 = "X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;;smtp:jblack@test.com;SMTP:jb@test.com";
        Regex splitEmailRegex = new Regex(@"(?<key>\w+?):(?<value>.*?)(\w+:|$)");

        List<string> sets = new List<string>();

        while (input2.Length > 0)
        {
            Match m1 = splitEmailRegex.Matches(input2)[0];
            string s1 = m1.Groups["key"].Value + ":" + m1.Groups["value"].Value;
            sets.Add(s1);
            input2 = input2.Substring(s1.Length);
        }

        foreach (var set in sets)
        {
            Console.WriteLine(set);
        }

        Console.ReadLine();

Конечно, многие будут требовать регулярных выражений: теперь у вас есть две проблемы. Может даже быть лучший ответ регулярного выражения, чем этот.

1 голос
/ 27 января 2009

Это привлекло мое любопытство .... Так что этот код на самом деле делает свою работу, но опять же хочет привести в порядок:)

Моя последняя попытка - прекратить менять то, что вам нужно; =)

static void Main(string[] args)
{
    string fneh = "X400:C=US400;A= ;P=Test;O=Exchange;S=Jack;G=Black;x400:C=US400l;A= l;P=Testl;O=Exchangel;S=Jackl;G=Blackl;smtp:jblack@test.com;X500:C=US500;A= ;P=Test;O=Exchange;S=Jack;G=Black;SMTP:jb@test.com;";

    string[] parts = fneh.Split(new char[] { ';' });

    List<string> addresses = new List<string>();
    StringBuilder address = new StringBuilder();
    foreach (string part in parts)
    {
        if (part.Contains(":"))
        {
            if (address.Length > 0)
            {
                addresses.Add(semiColonCorrection(address.ToString()));
            }
            address = new StringBuilder();
            address.Append(part);
        }
        else
        {
            address.AppendFormat(";{0}", part);
        }
    }
    addresses.Add(semiColonCorrection(address.ToString()));

    foreach (string emailAddress in addresses)
    {
        Console.WriteLine(emailAddress);
    }
    Console.ReadKey();
}
private static string semiColonCorrection(string address)
{
    if ((address.StartsWith("x", StringComparison.InvariantCultureIgnoreCase)) && (!address.EndsWith(";")))
    {
        return string.Format("{0};", address);
    }
    else
    {
        return address;
    }
}
1 голос
/ 27 января 2009

http://msdn.microsoft.com/en-us/library/c1bs0eda.aspx отметьте здесь, вы можете указать количество разделений, которые вы хотите. так что в вашем случае вы бы сделали

string.split(new char[]{';'}, 3);
0 голосов
/ 27 января 2009

Это работает!

    string input =
        "smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";
    string[] parts = input.Split(';');
    List<string> output = new List<string>();
    foreach(string part in parts)
    {
        if (part.Contains(":"))
        {
            output.Add(part + ";");
        }
        else if (part.Length > 0)
        {
            output[output.Count - 1] += part + ";";
        }
    }
    foreach(string s in output)
    {
        Console.WriteLine(s);
    }
0 голосов
/ 27 января 2009

Много попыток. Вот мой;)

string src = "smtp:jblack@test.com;SMTP:jb@test.com;X400:C=US;A= ;P=Test;O=Exchange;S=Jack;G=Black;";

Regex r = new Regex(@"
   (?:^|;)smtp:(?<smtp>([^;]*(?=;|$)))|
   (?:^|;)x400:(?<X400>.*?)(?=;x400|;x500|;smtp|$)|
   (?:^|;)x500:(?<X500>.*?)(?=;x400|;x500|;smtp|$)",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

foreach (Match m in r.Matches(src))
{
    if (m.Groups["smtp"].Captures.Count != 0)
        Console.WriteLine("smtp: {0}", m.Groups["smtp"]);
    else if (m.Groups["X400"].Captures.Count != 0)
        Console.WriteLine("X400: {0}", m.Groups["X400"]);
    else if (m.Groups["X500"].Captures.Count != 0)
        Console.WriteLine("X500: {0}", m.Groups["X500"]);   
}

Это находит все SMTP-адреса, x400 или x500 в строке в любом порядке появления. Он также определяет тип адреса, готового для дальнейшей обработки. Появление текста smtp, x400 или x500 в самих адресах не нарушит закономерности.

0 голосов
/ 27 января 2009

вот еще одно возможное решение.

string[] bits = text.Replace(";smtp", "|smtp").Replace(";SMTP", "|SMTP").Replace(";X400", "|X400").Split(new char[] { '|' });

биты [0], биты [1] и биты [2] будет содержать три части в порядке от вашей исходной строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...