Regex получает индекс первого символа не в двойных кавычках - PullRequest
0 голосов
/ 18 января 2019

Я ищу регулярное выражение для следующих действий:

  • Возвращает индекс первого экземпляра данного символа, не входящего в двойные кавычки (я могу гарантировать, что совпадающая двойная кавычка закрытия всегда будетнастоящее и символ для поиска сам по себе никогда не будет двойной кавычкой)
  • Разрешить, начиная с int startIndex позиция

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

Примеры (все примеры настроены на поиск !, но это не всегда так):

  • !something - должен возвращаться0
  • ! также должен возвращать 0
  • something! должен возвращаться 9
  • "something!" должен выходить из строя
  • "some!thing"! должен возвращаться 12
  • !"!"! должен вернуться 0
  • ""! должен вернуться 2
  • ""!"" должен вернуться 2
  • !something с startIndex == 2 если произойдет сбой
  • !something! с startIndex == 2 должен вернуть 10 (несмотря на то, что начиная с позиции 2, индекс чарсаacter для данной строки по-прежнему 10)

Так как это для .NET, намерение состоит в использовании Regex.Match().Index (если не предоставлена ​​лучшая альтернатива).

Ответы [ 2 ]

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

Если вам действительно нужна версия регулярного выражения, вы можете использовать шаблон следующим образом.

"(?<searchTerm>!)(?=(?:[^\"]|\"[^\"]*\")*$)"

Пример, для ввода

var input = new []
    {
    new {Key= "!something", BeginIndex=0},
    new {Key= "!", BeginIndex=0},
    new {Key= "something!", BeginIndex=0},
    new {Key= "\"something!\"", BeginIndex=0},
    new {Key= "\"some!thing\"!", BeginIndex=0},
    new {Key= "!\"!\"!", BeginIndex=0},
    new {Key= "\"\"!", BeginIndex=0},
    new {Key= "\"\"!\"\"", BeginIndex=0},
    new {Key= "!something", BeginIndex=2},
    new {Key= "!something!", BeginIndex=2},
    new {Key="!\"some!thing\"!",BeginIndex=5}
    };

Вы можете искать в индексе следующим образом

var pattern = "(?<searchTerm>!)(?=(?:[^\"]|\"[^\"]*\")*$)";
Regex regex = new Regex(pattern,RegexOptions.Compiled);
foreach(var str in input)
{
    var index = str.Key.GetIndex(regex,str.BeginIndex);
    Console.WriteLine($"String:{str.Key} , Index : {index}");
}

Где GetIndex определяется как

public static class Extension
{
    public static int GetIndex(this string source,Regex regex,int beginIndex=0)
    {
        var match = regex.Match(source);
        while(match.Success)
        {   

            if(match.Groups["searchTerm"].Index >= beginIndex)
                return match.Groups["searchTerm"].Index;

            match = match.NextMatch();
        }
        return -1;
    }
}

выход

String:!something , Index : 0
String:! , Index : 0
String:something! , Index : 9
String:"something!" , Index : -1
String:"some!thing"! , Index : 12
String:!"!"! , Index : 0
String:""! , Index : 2
String:""!"" , Index : 2
String:!something , Index : -1
String:!something! , Index : 10
String:!"some!thing"! , Index : 13

Надеюсь, это поможет.

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

Я предлагаю старый for цикл вместо регулярных выражений ; давайте реализуем это как метод расширения:

  public static partial class StringExtensions {
    public static int IndexOfQuoted(this string value,
                                    char toFind,
                                    int startPosition = 0,
                                    char quotation = '"') {
      if (string.IsNullOrEmpty(value))
        return -1;

      bool inQuotation = false;

      for (int i = 0; i < value.Length; ++i)
        if (inQuotation)
          inQuotation = value[i] != quotation;
        else if (value[i] == toFind && i >= startPosition)
          return i;
        else
          inQuotation = value[i] == quotation;

      return -1;
    }
  }

И так, вы можете использовать его, как если бы IndexOfQuoted a string s метод:

  string source = "something!";
  int result = source.IndexOfQuoted('!'); 

Демо-версия:

  string[] tests = new string[] {
    "!something",
    "!",
    "something!",
    "\"something!\"",
    "\"some!thing\"!",
    "!\"!\"!",
    "\"\"!",
    "\"\"!\"\"",
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,-20} -> {test.IndexOfQuoted('!')}"));

  Console.Write(report);

Результат:

!something           -> 0
!                    -> 0
something!           -> 9
"something!"         -> -1
"some!thing"!        -> 12
!"!"!                -> 0
""!                  -> 2
""!""                -> 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...