как разделить только самое внешнее - PullRequest
0 голосов
/ 24 августа 2018

У меня есть строка утверждения, подобная этой:

    *
    | { table_name | view_name | table_alias }.*
    | {
        [ { table_name | view_name | table_alias }. ]
        { column_name | $IDENTITY | $ROWGUID }
        | udt_column_name [ { . | :: } { { property_name | field_name } | method_name ( argument [ ,...n] ) } ]
        | expression
        [ [ AS ] column_alias ]
      }
    | column_alias = expression 

Мне нужны только самые внешние элементы, поэтому я использую char | для разделения содержимого, я хочу исключить любые |, существующие в скобках.
Результатом разделения является то, что у него есть 4 элемента, например:

# 1 *
# 2 { table_name | view_name | table_alias }.*
# 3 { [ { table_name | view_name | table_alias }. ] { column_name | $IDENTITY | $ROWGUID } | udt_column_name [ { . | :: } { { property_name | field_name } | method_name ( argument [ ,...n] ) } ] | expression [ [ AS ] column_alias ] }

# 4 column_alias = expression

Я пробовал что-то вроде (?m)\s*^\|\s* или ^(({\|\s*})({\{})?)({.+})$, но это просто дало мне ОДИН предмет, а не ЧЕТЫРЕ.
Спасибо за помощь @Wiktor Stribiżew и @Rui Jarimba.

У меня есть идея (?<!\{[^\}]*)\|(?![^\{]*\}), и я получаю вот так:

# 1 *
# 2 { table_name | view_name | table_alias }.*
# 3

 {
                [ { table_name | view_name | table_alias }. ]
                { column_name | $IDENTITY | $ROWGUID }

# 4

udt_column_name [ { . | :: } { { property_name | field_name } | method_name ( argument [ ,...n] ) } ]
                    | expression
                    [ [ AS ] column_alias ]
                  }

# 5 column_alias = expression

Теперь мне нужно внести изменения, чтобы исправить (?<!\{[^\}]*)\|(?![^\{]*\}) и очистить # 4 ....

хорошо, я нахожу шаблон, может быть, он не идеален, но это работа. это так:

Regex.Split(s, @"(?<!\{(?>[^\{\}]+|\{(?<D>)|\}(?<-D>))*(?(D)(?!)))\|(?!(?>[^\{\}]+|\{(?<D>)|\}(?<-D>))*(?(D)(?!))\})")

Наконец, я хотел бы поблагодарить всех, кто снова помог мне.

1 Ответ

0 голосов
/ 24 августа 2018

Вот так:

using System.Text.RegularExpressions;

static void Main(string[] args)
{
    string text = @"*
    | { table_name | view_name | table_alias }.*
    | {
        [ { table_name | view_name | table_alias }. ]
        { column_name | $IDENTITY | $ROWGUID }
        | udt_column_name [ { . | :: } { { property_name | field_name } | method_name ( argument [ ,...n] ) } ]
        | expression
        [ [ AS ] column_alias ]
    }
    | column_alias = expression";


    string pattern = BuildPattern();
    RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline;


    // solution 1: using a MatchEvaluator(Match) delegate
    string normalizedText = Regex.Replace(text, pattern, GetNormalizedLine, options);

    // solution 2: using replacement groups
    string normalizedText2 = Regex.Replace(text, pattern, "$3$4", options);

    bool areEqual = normalizedText2.Equals(normalizedText);

    Console.Read();
}

private static string BuildPattern()
{
    // '|' is special character, needs to be escaped. 
    // Assuming there might be some whitespace after the pipe
    string pipe = @"\|\s*";

    // '{' is special character, needs to be escaped. 
    string bracket = @"\{";

    // remaining text in the line
    string otherText = @".+";

    // using parenthesis () to group the results
    string pattern = $"^(({pipe})({bracket})?)({otherText})$";

    return pattern;
}

private static string GetNormalizedLine(Match match)
{
    GroupCollection groups = match.Groups;

    return $"{groups[3].Value}{groups[4].Value}";
}

Выводится следующая строка:

*
{ table_name | view_name | table_alias }.*
{
    [ { table_name | view_name | table_alias }. ]
    { column_name | $IDENTITY | $ROWGUID }
    | udt_column_name [ { . | :: } { { property_name | field_name } | method_name ( argument [ ,...n] ) } ]
    | expression
    [ [ AS ] column_alias ]
  }
column_alias = expression

EDIT

Я не использую Regex.Split (), как указано в OP, поскольку не думаю, что необходимо удалять символ |. Получить массив со всеми строками (кроме пробелов) просто:

string[] lines = normalizedText.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);

Некоторые заметки:

  • Я предполагаю, что удаляемый символ | всегда находится в начале строки, т. Е. Нет пробела до этого символа
  • Я предполагаю, что может быть пробелом между символами | и {
  • Я использую скобки для группировки совпадений (см. Группы регулярных выражений в C # )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...