2010-09-27 5 views
3

Я не уверен, как это сделать с помощью регулярного выражение (или, если можно, я новичок в регулярном выражении). У меня есть значение угла, которое вводит пользователь, и я пытаюсь проверить его. Он находится в форме градусов-минут-секунд. Проблема, с которой я сталкиваюсь, заключается в том, что если пользователь ошибочно использует секундную часть, я должен поймать эту ошибку, но мой матч за градусы-минуты - это успех.Шаблон совпадения [0-9] - [0-9] - [0-9], но без соответствия [0-9] - [0-9]

Возможно, этот метод будет лучше объяснить:

private Boolean isTextValid(String _angleValue) { 

     Regex _degreeMatchPattern = new Regex("0*[1-9]"); 
     Regex degreeMinMatchPattern = new Regex("(0*[0-9]-{1}0*[0-9]){1}"); 
     Regex degreeMinSecMatchPattern = new Regex("0*[0-9]-{1}0*[0-9]-{1}0*[0-9]"); 

     Match _degreeMatch, _degreeMinMatch, _degreeMinSecMatch; 

     _degreeMinSecMatch = degreeMinSecMatchPattern.Match(_angleValue); 
     if (_degreeMinSecMatch.Success) 
      return true; 

     _degreeMinMatch = degreeMinMatchPattern.Match(_angleValue); 
     if (_degreeMinMatch.Success) 
      return true; 

     _degreeMatch = _degreeMatchPattern.Match(_angleValue); 
     if (_degreeMatch.Success) 
      return true; 

     return false; 
    } 
} 

Я хочу, чтобы проверить градусы-минуты, если матч градусы-минуты-секунды не удается, но только если пользователь не вводить какие-либо данные секунд. Могу ли я сделать это с помощью регулярного выражения, или мне нужно проанализировать строку и оценить каждую часть отдельно? Благодарю.

EDIT: Пример данных будет 45-23-10 в качестве правильных данных. Проблема 45-23 также является достоверными данными; понимается 0 секунд. Поэтому, если пользователь набирает 45-23-1 = при аварии, регулярное выражение степениMinMatchPattern в моем коде будет успешно соответствовать, даже если оно недействительно.

Второй РЕДАКТ: просто для того, чтобы это стало ясно, минуты и вторая части являются необязательными. Пользователь может ввести 45, и это действительно.

+1

у вас есть какие-то данные? –

+0

Это было 45-23-1 =. Я думаю, вы просто не видели знак равенства. Возможно, лучшим примером является 45-23-1A. Извините за путаницу. – Shawn

ответ

2

Во-первых, символ по регулярному выражению один раз по умолчанию, поэтому {1} ​​является избыточным.

Во-вторых, поскольку вы можете, по-видимому, изолировать это значение (вы запрашиваете только это значение, вместо того, чтобы искать его в абзаце введенных данных), вы должны включить^и $ в свою строку, чтобы обеспечить, чтобы строка должен содержать ТОЛЬКО этот шаблон.

Попробуйте "^ \ d {1,3} - \ d {1,2} (- \ d {1,2})? $".

Нарушение этого правила:^соответствует началу строки. \ d соответствует любому десятичному символу, а затем позади этого вы указываете {1,3}, который будет соответствовать набору от одного до трех вхождений любой цифры. Затем вы ищете одну тире, затем аналогичный десятичный шаблон, но только один или два раза. Последний член заключен в круглые скобки, поэтому мы можем сгруппировать символы. Его форма похожа на первые две, тогда есть? который помечает предыдущую группу символов как необязательную. Значение $ в конце указывает, что вход должен завершиться. Учитывая это, он будет соответствовать 222-33-44 или 222-33, но не 222-3344 или 222-33-abc.

Имейте в виду, что есть дополнительные правила, которые вы, возможно, захотите включить. Например, секунды могут быть выражены как десятичные (если требуется разрешение меньше одной секунды). Вам необязательно ожидать десятичную точку и одну или несколько дополнительных цифр. Кроме того, вы, вероятно, имеете значение максимальной степени; указанное выше регулярное выражение будет соответствовать максимальному значению DMS 359-59-59, однако оно также будет соответствовать 999-99-99, что недопустимо. Вы можете ограничить максимальное значение с помощью регулярного выражения (например, «(3 [0-5] \ d | [1-2] \ d {2} | \ d {1,2})" будет соответствовать любому числу от 0 до 359 , сопоставляя 3, затем 0-5, затем 0-9, ИЛИ любое 3-значное число, начинающееся с 1 или 2, ИЛИ любое двузначное число), но в качестве примера показано, что регулярное выражение будет длинным и беспорядочным, поэтому хорошо документируйте код в том, что вы делаете.

+0

С незначительной модификацией (поскольку вторая из трех также является необязательной, а для C# требуется вторая обратная косая черта, чтобы должным образом избежать d) это сработало. Моим окончательным выражением является «^ \\ d {1,3} (- \\ d {1,2} (- \\ d {1,2})?)? $« Спасибо! – Shawn

+0

Если вы положили @ перед двойной кавычкой, которая открывает строку, .NET автоматически удалит любые символы, которые в ней нуждаются. Это полезно для файлов (разделители каталогов обратной косой черты) и многострочных данных (\ r \ n везде), а также для регулярных выражений. – KeithS

+0

И я кое-что узнал и сегодня (я знал о многострочных данных, но не о регулярном выражении). Благодаря! – Shawn

1

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

0

Я не уверен, что я правильно понимаю, но я думаю, что

(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$ 

может работать.

Но это довольно неоднозначно; также мне интересно, почему вы допускаете только однозначные градусы/минуты/секунды. Пожалуйста, покажите несколько примеров, которые вы делаете, и не хотите совпадать.

4

Вы можете указать «эта часть шаблона должна соответствовать как минимум 3 раза» с использованием синтаксиса {m,}. Поскольку существует дефис между каждым компонентом, указать первую часть отдельно, а затем каждая комбинация дефис цифр могут быть сгруппированы вместе после того, как:

`[0-9](-[0-9]){2,}` 

Вы можете также сократить [0-9] к \d: \d(-\d){2,}

+0

Я думаю, что он хочет сопоставить 2 * или * 3 числа, но 2 числа, только если ничего не следует, а не если произойдет некорректный ввод. –

0

Может быть, вы должны попробовать что-то вроде этого и тест на пустые/поврежденные группы:

Regex degrees = new Regex(
       @"(?<degrees>\d+)(?:-(?<minutes>\d+))?(?:-(?<seconds>\d+))?"); 
string[] samples = new []{ "123", "123-456", "123-456-789" }; 
foreach (var sample in samples) 
{ 
    Match m = degrees.Match(sample); 
    if(m.Success) 
    { 
     string degrees = m.Groups["degrees"].Value; 
     string minutes = m.Groups["minutes"].Value; 
     string seconds = m.Groups["seconds"].Value; 
     Console.WriteLine("{0}°{1}'{2}\"", degrees, 
      String.IsNullOrEmpty(minutes) ? "0" : minutes, 
      String.IsNullOrEmpty(seconds) ? "0" : seconds 
     ); 
    } 
}