Разбить строку на пробелы определенной длины - PullRequest
1 голос
/ 03 апреля 2020

Мне нужно разделить строки адреса на 3 части, каждая разного размера. В этом случае: 40, 30 и 30 символов. Я хочу разделить входную строку пробелами, чтобы это имело некоторый смысл.

Для этого я написал регулярное выражение: (.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1} и попробовал его на этом сайте: https://regex101.com. Это сработало!

Я перешел в Visual Studio, чтобы написать код, чтобы проверить его:

public static void TEST()
{
    List<string> ok = new List<string>();
    List<string> err = new List<string>();

    var lista = GetLista();
    foreach (string dir in lista)
    {
        Regex regex = new Regex(@"(.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}");
        dir = dir.Trim();

        GroupCollection cap = regex.Match(dir).Groups;

        if (cap.Count == 0) err.Add(dir);
        else ok.Add($"{dir};{cap[0].Value};{(cap.Count > 1 ? cap[1].Value.Trim() : "")};{(cap.Count > 2 ? cap[2].Value : "")};{(cap.Count > 3 ? cap[3].Value.Trim() : "")}";);
    }

    File.WriteAllLines("ok.txt", txt);
    File.WriteAllLines("er.txt", err);
}

Результаты очень разные, они совсем не совпадают. Являются ли регулярные выражения каким-то другим образом в C#?

Есть ли другой способ добиться этого?


РЕДАКТИРОВАНИЕ: регулярные выражения даны где отличия.


ОБНОВЛЕНИЕ Я приведу пример. Давайте возьмем следующую строку: "ЭРИК АДЕСИР КОМПАНИ ЛА ИСЛА ДЕ Л";; "ЭРИК АДЕСИР КОМПАНИ ЛА ИСЛА ДЕ Л" ;;

Требуются: "ERIK ADESIR COMPANY LA ISLA DE"; "LA PALMA"; ""

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

Ответы [ 2 ]

2 голосов
/ 03 апреля 2020

Вы хотите сопоставить всю строку, поэтому вам нужно добавить якоря, ^ и $. Затем вам нужно получить захваченные подстроки , а не полное совпадение . Обратите внимание, что GroupCollection возвращает все захваченные значения группы и все совпадение в качестве первого элемента. Таким образом, вы match.Groups будете содержать 1 + количество значений групп захвата. Вы должны игнорировать первый элемент.

Кроме того, чтобы проверить соответствие группы, вам нужно использовать cap[x].Success вместо cap.Count > x.

Итак, вам нужен такой код :

foreach (string dir in lista)
{
    var match = Regex.Match(dir, @"^(.{1,32})([ ]+.{1,30})?([ ]+.{1,30})?$");
    if (match.Success)
    {
        var cap = match.Groups;
        ok.Add($"{dir};{cap[1].Value};{(cap[2].Success ? cap[2].Value.Trim() : "")};{(cap[3].Success ? cap[3].Value : "")}");
    }
    else
    {
         err.Add(dir);
    }
}

См. C# демо онлайн:

List<string> ok = new List<string>();
List<string> err = new List<string>();

var lista = new[] { "ERIK ADESIR COMPANY LA ISLA DE LA PALMA" };
foreach (string dir in lista)
{
    var match = Regex.Match(dir, @"^(.{1,32})([ ]+.{1,30})?([ ]+.{1,30})?$");
    if (match.Success)
    {
        var cap = match.Groups;
        ok.Add($"{dir};{cap[1].Value};{(cap[2].Success ? cap[2].Value.Trim() : "")};{(cap[3].Success ? cap[3].Value : "")}");
    }
    else
    {
         err.Add(dir);
    }
}
Console.WriteLine(string.Join("\n", ok));

Выход:

ERIK ADESIR COMPANY LA ISLA DE LA PALMA;ERIK ADESIR COMPANY LA ISLA DE;LA PALMA;
0 голосов
/ 03 апреля 2020

Проблема может заключаться в том, что заданное вами регулярное выражение в c#

new Regex(@"(.{1,40})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}");

не равно тому, которое вы использовали в качестве теста:

(.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}

В c#, который вы запускаете с (. {1, 40 }, но ваш пример (({{, 32 })

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