C #: определение, если строка похожа на этот шаблон; возможное регулярное выражение - PullRequest
2 голосов
/ 27 августа 2009

Рассмотрим строку, которая выглядит следующим образом:

RR1 S5 C92

Это адрес сельского маршрута для доставки почты за городом: Сельский маршрут, Участок, Купе. За каждой буквой следует число и пробел. Обычно от одной до трех цифр, но вы никогда не знаете, сколько это может быть! Если пользователь ленив, он может ввести ноль, один или несколько пробелов.

Вопрос: Какое регулярное выражение ВЫ использовали бы, чтобы определить, соответствует ли данная строка этому шаблону?

Его использование будет примерно таким:

string ruralPattern; //a regex pattern here
bool isRural = Regex.Match(someString, ruralPattern);

Обновление: Спасибо за ваши предложения! Производительность и использование будут в статическом методе в сборке, вызываемой из веб-службы. Строки, проверяемые по этому шаблону, будут содержать не более 50 символов. Метод будет вызываться примерно раз в 5 секунд. Любые предложения по сохранению статичности? Очень ценится!

Ответы [ 4 ]

9 голосов
/ 27 августа 2009

Это должно работать:

^[Rr][Rr]\d+ *[Ss]\d+ *[Cc]\d+$

или согласно другому комментарию

^[Rr][Rr][0-9]+ *[Ss][0-9]+ *[Cc][0-9]+$

Что все это значит:

  • ^ - начало строки
  • [Rr] - следующий символ должен быть R или r
  • [Rr] - следующий символ должен быть R или r
  • \ d + или [0-9] + - следующая часть должна состоять из 1 или более цифр
  • (пробел) * - допускается 0 или более пробелов
  • [Ss] - следующий символ должен быть S или s
  • \ d + или [0-9] + - следующая часть должна состоять из 1 или более цифр
  • (пробел) * - допускается 0 или более пробелов
  • [Cc] - следующий символ должен быть C или c
  • \ d + или [0-9] + - следующая часть должна состоять из 1 или более цифр
  • $ - конец строки

Возможно, есть более элегантное решение, но его довольно легко прочитать.

Редактировать: Обновлен с учетом ввода некоторых комментариев

3 голосов
/ 27 августа 2009

Как насчет ...

someString = someString.Trim(); // eliminate leading/trailing whitespace
bool isRural = Regex.Match(
   someString,
   @"^rr\d+\s*s\d+\s*c\d+$",
   RegexOptions.IgnoreCase);

Это исключает переключение прописных / строчных букв в шаблоне и использует \s, чтобы разрешить любой (не символ новой строки) пробел (например, табуляции). Если вам нужны только пробелы, то '\s' следует изменить на ' '.

1 голос
/ 27 августа 2009

Давайте уточним следующие предположения:

  1. В строке есть три раздела.
  2. раздел 1 всегда начинается с прописных или строчных букв RR и заканчивается одной или несколькими десятичными цифрами.
  3. раздел 2 всегда начинается с заглавных или строчных букв S и заканчивается одной или несколькими десятичными цифрами.
  4. раздел 3 всегда начинается с буквы C сверху или снизу и заканчивается одной или несколькими десятичными цифрами.

Для простоты достаточно следующего.

[Rr][Rr][0-9]+[ ]+[Ss][0-9]+[ ]+[Cc][0-9]+
  1. [Rr] означает ровно один алфавит R, верхний или нижний регистр.
  2. [0-9] означает ровно один десятичный знак цифра.
  3. [0-9] + означает, по крайней мере, один или более, десятичные цифры.
  4. [] + означает, по крайней мере, один или более, пространства.

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

Поэтому следующее регулярное выражение более полезно.

([Rr][Rr][0-9]+)[ ]+([Ss][0-9]+)[ ]+([Cc][0-9]+)

Давайте применим это регулярное выражение к строке

string inputstr = "Holy Cow RR12 S53 C21";

Это то, что ваш сопоставитель регулярных выражений даст вам знать:

start pos=9, end pos=21
Group(0) = Rr12 S53 C21
Group(1) = Rr12
Group(2) = S53
Group(3) = C21

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

Компилятор regex будет вызывать совпадение

  1. вся подобранная строка как группа 0
  2. сельский маршрут как группа 1
  3. сайт как группа 2 и
  4. отделение как группа 3.

Естественно, группы 1, 2 и 3 будут встречать совпадения, если и только если группа 0 имеет совпадение.

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

string postalstr, rroute, site, compart;
if (match.group(0)!=null)
{
  int start = match.start(0);
  int end = match.end(0);
  postalstr = inputstr.substring(start, end);

  start = match.start(1);
  end = match.end(1);
  rroute = inputstr.substring(start, end);

  start = match.start(2);
  end = match.end(2);
  site = inputstr.substring(start, end);

  start = match.start(3);
  end = match.end(3);
  compart = inputstr.substring(start, end);
}

Кроме того, вы можете захотеть войти в таблицу базы данных со столбцами: rr, site ,арти, но вы хотите, чтобы вводились только цифры без алфавитов "rr", "s" или "c". Это будет регулярное выражение с вложенной группировкой для использования.

([Rr][Rr]([0-9]+))[ ]+([Ss]([0-9]+))[ ]+([Cc]([0-9]+))

И средство сопоставления сообщит вам следующее при совпадении для группы 0:

start=9, end=21
Group(0) = Rr12 S53 C21
Group(1) = Rr12
Group(2) = 12
Group(3) = S53
Group(4) = 53
Group(5) = C21
Group(6) = 21
0 голосов
/ 27 августа 2009

К вашему сведению: если вы собираетесь использовать этот RegEx для тестирования большого количества данных, лучше всего было бы сказать .NET прекомпилировать его - он будет скомпилирован в IL и даст повышение производительности, а не интерпретировать шаблон RegEx каждый раз. Укажите его как статический член в зависимости от того, какой класс содержит ваш метод, например:

private static Regex re = new Regex("pattern", RegexOptions.Compiled | RegexOptions.IgnoreCase);

... и метод для проверки соответствия строки шаблону ...

bool matchesString = re.IsMatch("string");

Удачи.

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