我想在字符串中捕捉罗马数字(80以下的数字足够好)。我在How do you match only valid roman numerals with a regular expression?找到了良好的基础。问题是:它处理整个字符串。我还没有找到如何检测字符串内的罗马数字的解决方案,因为没有强制要求,每个组都可以是可选的。到目前为止,我尝试过这样的事情:
my $x = ' some text I-LXIII iv more ';
if ( $x =~ s/\b(
(
(XC|XL|L?X{0,3}) # first group 10-90
|
(IX|IV|V?I{0,3}) # second group 1-9
)+
)
\b/>$1</xgi ) { # mark every occurrence
say $x;
}
__END__
><some>< ><text>< ><>I<><-><>LXIII<>< ><>iv<>< ><more><
desired output:
some text >I<->LXIII< >iv< more
所以,这个也可以通过自己捕获单词边界,因为所有组都是可选的。如何完成它?如何强制执行这两个组中的一组,而无法确定哪一组是强制性的?其他捕捉罗马人的方法也很受欢迎。
答案 0 :(得分:4)
您可以使用Roman CPAN模块
use Roman;
my $x = ' some text I-LXIII VII XCVI IIIXII iv more ';
if ( $x =~
s/\b
(
[IVXLC]+
)
\b
/isroman($1) ? ">$1<" : $1/exgi ) {
say $x;
}
<强>输出:强>
some text >I<->LXIII< >VII< >XCVI< IIIXII >iv< more
答案 1 :(得分:2)
这是Perl让我们失望的地方,其中缺少\<
和\>
(开头和结尾字边界)构造,这些构造在其他地方可用。即使\b...\b
不使用任何目标字符串,...
之类的模式也会匹配,因为第二个\b
将很快与第二次开始字边界匹配。
然而,结束词边界只是(?<=\w)(?!\w)
,所以我们可以使用它。
这个程序会做你想要的。它会对字边界中包含的一串潜在罗马字符进行预测(因此我们必须位于开头字边界),然后检查合法罗马数字后面没有单词字符(所以现在我们处于 end 字边界)。
请注意,我已经改变了你的>...<
标记,因为它们使我感到困惑。
use strict;
use warnings;
use feature 'say';
my $x = ' some text I-LXIII iv more ';
if ( $x =~ s{
(?= \b [CLXVI]+ \b )
(
(?:XC|XL|L?X{0,3})?
(?:IX|IV|V?I{0,3})?
)
(?!\w)
}
{<$1>}xgi ) {
say $x;
}
<强>输出强>
some text <I>-<LXIII> <iv> more