Оптимизируйте следующее регулярное выражение - PullRequest
0 голосов
/ 15 января 2019

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

  • Должен начинаться с [
  • Должен содержать ]
  • Разрешено иметь любые символы (включая пробелы) между [ и ]
  • Должен содержать хотя бы один символ от [ до ]
  • Разрешено иметь ; после ]. После ; разрешены все символы (хотя это и неважно, поскольку меня это не волнует)
  • Если и только если a ; после ] присутствует, пробелы (читайте табуляции, пробелы - хотя я могу гарантировать, что \r\n\f\v не будет, поэтому я и использовал \s ниже) допускаются между ] и ;. Если ; отсутствует после ], тогда ] должен быть концом строки.

Я получил следующее регулярное выражение, которое прошло все мои начальные тесты: ^\[([^]]+)](?:\s+?;)?.

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

Я не совсем уверен, было ли здесь полезно использовать lookahead.

EDIT

например:

[some;thing] - Действительный, с группой захвата some;thing

[something] - Действительный, с группой захвата something

[something] - недействительно, не начинается с [

[something] ;ojasodj - Действительный, группа захвата something

[something] - Неверно, пробел после ] без ; настоящего

[something]; - Действительный, группа захвата something

[] - Неверно, должен содержать хотя бы один символ от [ до ]

Ответы [ 3 ]

0 голосов
/ 15 января 2019

TL; DR: ^\[([^]]+)](?:$|\s*;)

^\[([^]]+)] уже является оптимальным способом сопоставления первой части вашего регулярного выражения, если только вы не можете удалить группу захвата. Используя отрицательный класс символов, вы избегаете любого ненужного возврата в неудачных случаях, которые могут быть связаны с любым типом .* или .*? шаблона.

Чтобы выполнить другие ваши правила, вам нужно либо сопоставить конец строки ($), либо необязательные пробелы и точку с запятой, так что должно быть (?:$|\s*;). Я бы поставил сначала $, так как это более короткое совпадение (таким образом, более быстрый успех), но это также зависит от ваших данных (если во втором случае будет подавляющее большинство, укажите это первым).

Полная картина: ^\[([^]]+)](?:$|\s*;)

Имейте в виду, что за $ может следовать необязательный \n, но ваши тестовые примеры не выглядят многострочными:)

0 голосов
/ 15 января 2019

Вот как вы можете сделать это с помощью кода вместо

public static bool IsValid(string str, out string capture)
{
    capture = null;

    // A null string is invalid
    if(str == null) return false;

    // An empty string is invalid
    if(str.Length == 0) return false;

    // A string that does not start with [ is invalid
    if(str[0] != '[') return false;
    int end = str.IndexOf(']');

    // A string that does not have a ] is invalid
    if(end == -1) return false;

    // A string that does not have anything between the [ and ] is invalid
    if(end == 1) return false;

    // if the ] is not the end of the string we need to look for a ;.
    if(end != str.Length -1)
    {
        bool semicolon = false
        for(int i = end + 1; i < str.Length; i++)
        {
            // ; found so we can stop looking at characters.
            if(str[i] == ';') 
            {
                semicolon = true;
                break;
            }

            // If non-whitespace is between the ] and ; the string is invalid
            if(!char.IsWhiteSpace(str[i])) return false;
        }

        // No ; found so the string is invalid
        if(!semicolon) return false;
    }

    // Capture the string between [ and ]
    capture = str.Substring(1,end - 1);
    return true;
}

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

0 голосов
/ 15 января 2019

Попробуйте этот шаблон ^\[[^\]]+\](?(?=\s*;)\s*;.*|$)

Пояснение:

^\[[^\]]+\] будет соответствовать тексту, заключенному в квадратные скобки в начале строки (^) (хотя бы один символ, отличный от ] внутри них).

(?(?=\s*;)\s*;.*|$) - если то, что следует после заключающей квадратную скобку, состоит только из пробелов и точек с запятой, сопоставьте их, в противном случае убедитесь, что это конец строки ($).

Демо

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