Я пытаюсь настроить серию регулярных выражений для сопоставления неизвестных входящих данных.
Что я хочу сделать, так это определить, соответствует ли каждое выражение данным, не может ли они совпадать или может соответствовать данным на данный момент.
Например, если у нас есть следующие регулярные выражения:
\Aaaab
\Aaaac
\Abbb
Тогда, если мы уже получили aa
, то первые два могут совпадать, в зависимости от того, что будет дальше, но третий никогда не совпадет.
Если мы получим еще немного и получим aaac
, то первое не будет совпадать, второе совпадет, а третье все равно не совпадет.
В Java это можно сделать так:
Pattern pattern = Pattern.compile("\Aaaab");
Matcher matcher = pattern.matcher(receivedSoFar);
if (matcher.matches())
{
// A match has been found now
}
else if (matcher.hitEnd())
{
// Doesn't match yet, but don't write it off, wait for more data.
}
else
{
// This pattern doesn't match at all, we can rule it out.
}
См. здесь рабочий пример.
Различие между «может соответствовать» и «не соответствует» важно, потому что, если мы достигнем точки, где ни один из шаблонов не может совпадать, нам нужно будет вызвать реакцию состояния ошибки.
Я искал способ реализовать это в C# DotNet и не смог его найти. Класс System.Text.RegularExpressions.Match
имеет только свойство Success
, которое сообщает нам, найдено ли совпадение, но не может сказать нам, возможно ли совпадение в будущем.
Есть ли способ сделать это в C# DotNet?
Я попробовал Google, документацию learn.microsoft.com
и даже, в отчаянии,
Отредактировано: Извините, я случайно упомянул requireEnd
, где имел в виду hitEnd
.
Как я видел в исходном коде, определение этой информации встроено в очень глубокие внутренние механизмы регулярных выражений в Java, поэтому переписывать ее на C# не очень практично.
@MichałTurczyn Спасибо, что указали на мою ошибку, я указал не на тот метод. Я исправил пример и дал ссылку на рабочий пример скрипки.
На самом деле, hitEnd всегда устанавливается в тех же местах, что и requireEnd, так что это все еще важная особенность Regex. будет сложно портировать его на C#
Здравствуйте и добро пожаловать! Как насчет того, чтобы просто поставить группу захвата после вашего шаблона и дополнительно захватить любой символ, например \Aaaa(.?)
и если что-то и было захвачено этой первой группой, то это было не в конце.
Посмотрите эту демоверсию .NET на tio.run
Или сравните позицию совпадения m.Index + длину совпадения с длиной строки. Однако это не будет работать для многострочного сопоставления (как в моей последней демонстрации).
@bobblebubble Спасибо за ваш вклад, но вы решаете ситуации, когда ввод длиннее, чем ожидает шаблон. Мне нужно обработать входные данные, которые могут оказаться короче, чем ожидает шаблон. Другими словами, мне нужно знать, соответствует ли полученное на данный момент началу шаблона, а не то, что шаблон соответствует началу того, что было получено.
Посмотрите https://github.com/ltrzesniewski/pcre-net (Perl-совместимые регулярные выражения для .NET)
В файле readme есть раздел о частичном совпадении, он может охватывать ваш вариант использования.
Я не знаю хорошего способа решить это требование с помощью внутренней реализации Regex .Net, поэтому лучшим выбором может быть использование альтернативной реализации nuget.
Это отлично работает, спасибо: dotnetfiddle.net/tofk8Q
Согласно документации Java:
If a match was not found, then requireEnd has no meaning.
Это означает, что ваш вариант использования недействителен. Таким образом, портировать его на C# нет смысла.