如何创建正则表达式检查罗马数字
How to create regular expression checking Roman numerals?
我需要创建正则表达式来验证用户是否输入:
- 4位OR
- 值,如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
4位数和后面的'-[A-Z]{2}
(对我来说)不言自明。我计算罗马数字的方法是:
- 打开Excel用1-33填充列
- 将该列转换为罗马数字(所有7种不同的变体)
- 检查这些品种是否与1-33不同(它们没有)
- 忙于将罗马数字移动到将其限制为33的最小数量的独特图案中(即,"然后你要数到三十三,不多也不少。三十三是你要数的数字,数数的数字是三十三。你不应该数三十四,也不应该数三十二,除非你再继续数三十三。三十五就对了。")
- 意识到多达三十九个是一个单一的模式(
^(([X]{0,3}([I]([XV]?|[I]{0,2})?|([V][I]{0,3})?)))$
,为了更好的清晰度,改为捕获组) - 更改了模式,最多可容纳二十九人
- 增加了另一个允许三十到三十九
- 构建整个模式,并在RegexBuddy(这是一个非常宝贵的工具)中针对数字0-20000和罗马数字1-150后面跟着"-AA"进行测试
- 这个模式奏效了,所以我把它贴了出来(然后又喝了一杯咖啡,自己管理了一个"阿塔男孩",完成了我认为是一个可爱的周六早上挑战)
我假定您所说的无关括号是指非捕获组(?: ... )
。我经常用这些来分组(在这里分组是非常必要的)。我让它们不捕获,因为我不需要捕获子组,只需要捕获父组(在这个用例中,我认为它们也不需要实际捕获,但这样做没有坏处)。通过使它们不被捕获,它们不会创建加速处理的反向引用(尽管对于单个输入,所获得的时间可以忽略不计)。
相关文章:
- 从链接进行正则表达式检查
- 正则表达式检查循环中的 [A-Z] 范围
- 用Javascript正则表达式检查像x.0.0这样的字符串
- Javascript正则表达式检查标志支持
- 通过正则表达式检查合法字符,但结果出乎意料
- 使用正则表达式检查数组条目
- 正则表达式检查正确的扩展名
- 正则表达式检查字符串中是否存在 http 或 https
- 是否可以在javascript中使用正则表达式检查输入中是否有多个特殊字符
- 正则表达式检查句子的单词
- 如何使用正则表达式检查三个字符长度
- 如何在 javascript 中使用正则表达式检查空的 json 响应
- 正则表达式检查 4 个连续数字
- 正则表达式检查所有数字是否相同
- 正则表达式检查字符串是否仅包含字母数字字符和空格 - javascript
- Javascript 正则表达式检查输入仅包含零
- JS正则表达式检查字符串的长度为字符数,介于最小值和最大值之间,不计算空格
- 如何创建正则表达式检查罗马数字
- 使用正则表达式检查javascript中文本框内容的长度
- 使用jquery正则表达式检查起始值