Как создать регулярное выражение, проверяющее римские цифры? - PullRequest
4 голосов
/ 18 февраля 2012

Мне нужно создать регулярное выражение, которое проверяет, если пользователь вводит:

  • 4 цифры ИЛИ
  • значение как XXXXXX-YY , где X - римские цифры от I до XXXIII, а YY - два латинских символа (A-Z)

Ответы [ 3 ]

3 голосов
/ 18 февраля 2012

В соответствии с требованиями возможны римские числовые форматы. Для удобства чтения показано только максимальное число X.

XXX III     (or: <empty>, I or II instead of III)
XX V       (or: IV, IX and X instead of IV)

Я предлагаю этот компактный шаблон:

/^(\d{4}|(?=[IVX])(X{0,3}I{0,3}|X{0,2}VI{0,3}|X{0,2}I?[VX])-[A-Z]{2})$/i

Пояснение:

^                Begin of string
(                Begin of group 1.
  \d{4}             4 digits

|                 OR

  (?=[IVX])         Look-ahead: Must be followed by a I, V or X
  (                  Begin of group 2.
     X{0,3}I{0,3}       = 0 1 2 3  + { 0 ; 10 ; 20 ; 30} (roman)
  |                  OR
     X{0,2}VI{0,3}      = 5 6 7 8  + { 0 ; 10 ; 20 }     (roman)
  |                  OR
     X{0,2}I?[VX]       = 4 9      + { 0 ; 10 ; 20 }     (roman)
  )                  End of group 2
  -[A-Z]{2}          Postfixed by a hyphen and two letters
)                 End of group 1.
$                End of string
2 голосов
/ 18 февраля 2012

Хорошо, часть, которая соответствует римской цифре между I и XXXIII, выглядит следующим образом:

(?:X(?:X(?:V(?:I(?:I?I)?)?|X(?:I(?:I?I)?)?|I(?:[VX]|I?I)?)?|V(?:I(?:I?I)?)?|I(?:[VX]|I?I)?)?|V(?:I(?:I?I)?)?|I(?:[VX]|I?I)?)

Как показано этим:

#!/usr/bin/env perl
use Regexp::Assemble;
use Roman;

my $ra = new Regexp::Assemble;

for my $num (1..33) {
    $ra->add(Roman($num));
} 

print $ra->re, "\n";
1 голос
/ 18 февраля 2012
function inputIsValid(value) {
    var r = /(^[0-9]{4}$)|(^(?:(?:[X]{0,2}(?:[I](?:[XV]?|[I]{0,2})?|(?:[V][I]{0,3})?))|(?:[X]{3}[I]{0,3}))\-[A-Z]{2}$)/ig;
    return value.match(r);
}

Это будет соответствовать либо 4-значному вводу, либо римскому номеру (от 1 до 33), за которым следуют тире и две буквы.

Чтобы объяснить регулярное выражение, ниже приведен расширенный источникс комментариями:

// Test for a 4-digit number
(                                       // Start required capturing group
    ^                                   // Start of string
    [0-9]{4}                            // Test for 0-9, exactly 4 times
    $                                   // End of string
)                                       // End required capturing group
|                                       // OR
// Test for Roman Numerals, 1 - 33, followed by a dash and two letters
(                                       // Start required capturing group
    ^                                   // Start of string
    (?:                                 // Start required non-capturing group
        // Test for 1 - 29
        (?:                             // Start required non-capturing group
            // Test for 10, 20, (and implied 0, although the Romans did not have a digit, or mathematical concept, for 0)
            [X]{0,2}                    // X, optionally up to 2 times
            (?:                         // Start required non-capturing group
                // Test for 1 - 4, and 9
                [I]                     // I, exactly once (I = 1)
                (?:                     // Start optional non-capturing group
                    // IV = 4, IX = 9
                    [XV]?               // Optional X or V, exactly once
                    |                   // OR
                    // II = 2, III = 3
                    [I]{0,2}            // Optional I, up to 2 times
                )?                      // End optional non-capturing group
                |                       // OR
                // Test for 5 - 8
                (?:                     // Start optional non-capturing group
                    [V][I]{0,3}         // Required V, followed by optional I, up to 3 times
                )?                      // End optional non-capturing group
            )                           // End required non-capturing group
        )                               // End required non-capturing group
        |                               // OR
        // Test for 30 - 33
        (?:                             // Start required non-capturing group
            // Test for 30
            [X]{3}                      // X exactly 3 times
            // Test for 1 - 3
            [I]{0,3}                    // Optional I, up to 3 times
        )                               // End required non-capturing group
    )                                   // End required non-capturing group
    // Test for dash and two letters
    \-                                  // Literal -, exactly 1 time
    [A-Z]{2}                            // Alphabetic character, exactly 2 times
    $                                   // End of string
)                                       // End required capturing group

Четырехзначный номер и трейлинг \-[A-Z]{2} были (для меня) очевидны.Мой метод для римских цифр состоял в следующем:

  1. Открыть Excel Заполните столбец 1-33.
  2. Преобразовать этот столбец в римские цифры (во всех 7 различных вариантах).
  3. Проверьте, не отличались ли какие-либо из разновидностей от 1-33 (они не были).
  4. Возились с перемещением римских цифр в минимальное количество уникальных узоров, ограничивающее их до 33 (то есть «тогда будешь считать до тридцати трех, не больше, не меньше. Тридцать три будет числом, которое ты считаешь, и число отсчетов должно быть тридцать три. Тридцать четыре ты не считаешь, нисосчитайте тридцать два, за исключением того, что вы затем переходите к тридцати трем. Тридцать пять прямо сейчас. ")
  5. Понял, что до тридцати девяти - это единый шаблон (^(([X]{0,3}([I]([XV]?|[I]{0,2})?|([V][I]{0,3})?)))$, измененный на захватгруппы для лучшей наглядности).
  6. Изменен шаблон для разрешения до двадцати девяти.
  7. Добавлен другой, чтобы разрешить от тридцати до тридцати девяти.
  8. Создайте весь шаблон и протестируйтев RegexBuddy(бесценный инструмент для этого материала) против цифр 0 - 20 000 и римских цифр 1 - 150, за которыми следует «-AA».
  9. Шаблон сработал, поэтому я разместил его (затем взял еще одну чашку кофе и сам-адобавил «мальчика-атташе» для выполнения того, что я считал прекрасным субботним утренним испытанием).

Под сторонними скобками я предполагаю, что вы имеете в виду группы без захвата (?: ... ).Я часто использую их для группировки вещей (и группировка здесь совершенно необходима).Я сделал их без захвата, потому что мне не нужно захватывать подгруппы, только родительские группы (и в этом случае использования я не думаю, что их нужно на самом деле захватывать, но это не мешает делать это).Делая их без захвата, они не будут создавать обратных ссылок, что ускоряет обработку (хотя для одного входа выигранное время незначительно).

...