Мне нужно создать регулярное выражение, которое проверяет, вводит ли пользователь:
- 4 цифры ИЛИ
- значение вида XXXXXX-YY, где X — римские цифры от I до XXXIII, а YY — два латинских символа (A-Z)
Мне нужно создать регулярное выражение, которое проверяет, вводит ли пользователь:
Согласно требованиям, это возможные форматы римских чисел. Для удобочитаемости показано только максимальное количество 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
Ну, часть, которая соответствует римской цифре между 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";
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}
в конце были (для меня) самоочевидными. Мой метод для римских цифр заключался в следующем:
^(([X]{0,3}([I]([XV]?|[I]{0,2})?|([V][I]{0,3})?)))$
, изменено на группы захвата для большей наглядности).Под посторонними скобками я предполагаю, что вы имеете в виду незахватывающие группы (?: ... )
. Я часто использую их для группировки вещей (и группировка здесь совершенно необходима). Я сделал их незахватывающими, потому что мне не нужно захватывать подгруппы, а только родительские группы (и в этом случае я не думаю, что их действительно нужно захватывать, но это не повредит). ). Делая их незахватывающими, они не будут создавать обратные ссылки, что ускоряет обработку (хотя для одного ввода выигрышное время незначительно).
[V][I]{0,3}
вместо VI{0,3}
. Кроме того, вы использовали неправильный символ комментария: регулярные выражения требуют #
. О, подождите, это Javascript, где вам запрещено использовать режим /x
или (?x)
. Javascript имеет худшие регулярные выражения из всех существующих языков. Просто ужасно. Тем не менее, плагин XRegExp немного помогает.
- person tchrist; 18.02.2012
[vV][iI]{0,3}
, а затем добавил переключатель без учета регистра (и удалил совпадения в нижнем регистре).
- person pete; 18.02.2012