c # совпадение с регулярным выражением по определенному индексу в строке? - PullRequest
6 голосов
/ 12 августа 2009

Я хотел бы проверить, будет ли регулярное выражение соответствовать части строки по определенному индексу (и только начиная с этого конкретного индекса). Например, учитывая строку «один два 3 4 пять», я хотел бы знать, что в индексе 8 регулярное выражение [0-9] + будет соответствовать «3». RegularExpression.IsMatch и Match оба берут начальный индекс, однако они оба при необходимости будут искать совпадение во всей оставшейся части строки.

string text="one two 3 4 five";
Regex num=new Regex("[0-9]+");

//unfortunately num.IsMatch(text,0) also finds a match and returns true
Console.WriteLine("{0} {1}",num.IsMatch(text, 8),num.IsMatch(text,0));

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

Я не хочу:

  1. разбить строку на некоторой границе как пробел, потому что в моем ситуация, которую я не буду знать заранее какая подходящая граница будет
  2. необходимо изменить входную строку в любым способом (например, получение подстроки в индексе 8, а затем с помощью ^ в регулярное выражение)
  3. поиск остальной части строка для матча или сделать что-нибудь иначе это не было бы для исполнителей большое количество тестов против большая строка.

Я хотел бы проанализировать потенциально большой текст, предоставленный пользователем, используя произвольную пользовательскую грамматику. Грамматика будет определена в BNF или PEG-подобном синтаксисе, а терминалы будут либо строковыми литералами, либо регулярными выражениями. Таким образом, мне нужно проверить, соответствует ли следующая часть строки какому-либо из потенциальных терминалов, управляемых грамматикой.

Ответы [ 4 ]

12 голосов
/ 12 августа 2009

Как насчет использования Regex.IsMatch(string, int) с использованием регулярного выражения, начинающегося с \G (что означает "начало последнего совпадения")?

Это похоже на работу:

using System;
using System.Text.RegularExpressions;

class Test
{
    static void Main()
    {
        string text="one two 3 4 five";
        Regex num=new Regex(@"\G[0-9]+");

        Console.WriteLine("{0} {1}",
                          num.IsMatch(text, 8), // True
                          num.IsMatch(text, 0)); // False
    }
}
2 голосов
/ 12 августа 2009

Если вы хотите искать только подстроку текста, возьмите эту подстроку перед регулярным выражением.

myRegex.Match(myString.Substring(8, 10));
1 голос
/ 12 августа 2009

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

^.{8}[\d]

, который будет совпадать, если между началом строки и цифрой есть 8 символов.

0 голосов
/ 12 августа 2009

Если вы знаете максимальную длину потенциального совпадения в проверяемой строке, это ограничит сканирование строки.

Если вы проверяете только числа, это, вероятно, проще, чем если вы проверяете произвольные выражения. Природа Regex - сканировать до конца, чтобы найти совпадение. Если вы хотите запретить сканирование, вам нужно указать длину или использовать что-то отличное от Regex.

string text = "one two 3 4 five";
Regex num = new Regex("[0-9]+");
int indexToCheck = 8;
int maxMatchLength = ...;
Match m = num.Match(text, indexToCheck, maxMatchLength);

Знаете ли вы что-нибудь о том, какие типы выражений могут быть запущены со строками, и будет ли сканирование всей строки слишком трудоемким?

num.Match вернет первый удар, если он существует, а затем остановит сканирование. Если вы хотите больше совпадений, вы должны вызвать m.NextMatch (), чтобы продолжить сканирование совпадений.

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